You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by GitBox <gi...@apache.org> on 2018/01/06 18:57:39 UTC
[GitHub] rhtyd closed pull request #2333: Add Java Default Certificat Authorities into the keystore if using a custom cert SSL
rhtyd closed pull request #2333: Add Java Default Certificat Authorities into the keystore if using a custom cert SSL
URL: https://github.com/apache/cloudstack/pull/2333
This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:
As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):
diff --git a/.travis.yml b/.travis.yml
index c4790edf4b0..032b4f47aeb 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -34,6 +34,7 @@ env:
matrix:
- TESTS="smoke/test_affinity_groups
smoke/test_affinity_groups_projects
+ smoke/test_certauthority_root
smoke/test_deploy_vgpu_enabled_vm
smoke/test_deploy_vm_iso
smoke/test_deploy_vm_root_resize
@@ -42,7 +43,10 @@ env:
smoke/test_disk_offerings
smoke/test_dynamicroles
smoke/test_global_settings
- smoke/test_guest_vlan_range
+ smoke/test_guest_vlan_range"
+
+ - TESTS="smoke/test_hostha_kvm
+ smoke/test_hostha_simulator
smoke/test_hosts
smoke/test_internal_lb
smoke/test_iso
@@ -51,21 +55,23 @@ env:
smoke/test_login
smoke/test_metrics_api
smoke/test_multipleips_per_nic
+ smoke/test_nested_virtualization
smoke/test_network
smoke/test_network_acl
smoke/test_nic
smoke/test_nic_adapter_type
- smoke/test_non_contigiousvlan"
-
- - TESTS="smoke/test_outofbandmanagement
+ smoke/test_non_contigiousvlan
+ smoke/test_outofbandmanagement
+ smoke/test_outofbandmanagement_nestedplugin
smoke/test_over_provisioning
smoke/test_password_server
smoke/test_portable_publicip
smoke/test_primary_storage
smoke/test_privategw_acl
smoke/test_public_ip_range
- smoke/test_pvlan
- smoke/test_regions
+ smoke/test_pvlan"
+
+ - TESTS="smoke/test_regions
smoke/test_reset_vm_on_reboot
smoke/test_resource_detail
smoke/test_router_dhcphosts
@@ -93,6 +99,7 @@ env:
smoke/misc/test_vm_sync"
- TESTS="component/find_hosts_for_migration
+ component/test_accounts
component/test_acl_isolatednetwork_delete
component/test_acl_listsnapshot
component/test_acl_listvm
@@ -119,14 +126,14 @@ env:
- TESTS="component/test_projects
component/test_project_configs
- component/test_project_limits
component/test_project_usage
component/test_regions
component/test_regions_accounts
component/test_routers
component/test_snapshots"
- - TESTS="component/test_resource_limits"
+ - TESTS="component/test_project_limits
+ component/test_resource_limits"
- TESTS="component/test_stopped_vm
component/test_tags
@@ -146,7 +153,6 @@ env:
# - TESTS="component/test_project_resources"
# - TESTS="component/test_cpu_domain_limits"
# - TESTS="component/test_acl_isolatednetwork"
-# - TESTS="component/test_accounts"
# - TESTS="component/test_organization_states"
before_install: travis_wait 30 ./tools/travis/before_install.sh
diff --git a/INSTALL.md b/INSTALL.md
index c69018daa15..626df91dc56 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -15,7 +15,7 @@ was tested against a CentOS 6.5 x86_64 setup.
Install tools and dependencies used for development:
$ yum install git ant ant-devel java-1.6.0-openjdk java-1.6.0-openjdk-devel
- mysql mysql-server tomcat6 mkisofs gcc python MySQL-python openssh-clients wget
+ mysql mysql-server mkisofs gcc python MySQL-python openssh-clients wget
# yum -y update
# yum -y install java-1.7.0-openjdk
@@ -124,7 +124,6 @@ To create debs install the following extra packages:
# apt-get -y install python-mysqldb
# apt-get -y install debhelper
- # apt-get -y install tomcat6
Then:
@@ -138,7 +137,6 @@ All the deb packages will be located one level down.
To create rpms, install the following extra packages:
# yum -y install rpm-build
- # yum -y install tomcat6
# yum -y install ws-commons-util
# yum -y instal gcc
# yum -y install glibc-devel
diff --git a/README.md b/README.md
index 57853280498..17a7a8f7bd9 100644
--- a/README.md
+++ b/README.md
@@ -42,7 +42,7 @@ For more information on Apache CloudStack, please visit the [website](http://clo
Apache CloudStack project uses Git. The official Git repository is at:
- https://git-wip-us.apache.org/repos/asf/cloudstack.git
+ https://gitbox.apache.org/repos/asf/cloudstack.git
And a mirror is hosted on Github:
diff --git a/agent/conf/agent.properties b/agent/conf/agent.properties
index 3ed382abb92..0354aceadab 100644
--- a/agent/conf/agent.properties
+++ b/agent/conf/agent.properties
@@ -176,7 +176,23 @@ hypervisor.type=kvm
# vm.rng.rate.period=1000
# The number of milliseconds in which the guest is allowed to obtain the bytes
# specified above.
-
+#
# router.aggregation.command.each.timeout=600
# timeout value for aggregation commands send to virtual router
#
+# host.overcommit.mem.mb = 0
+# allows to increase amount of ram available on host virtually to utilize Zswap, KSM features
+# and modern fast SSD/3D XPoint devices. Specified amount of MBs is added to the memory agent
+# reports to the Management Server
+# Default: 0
+#
+# vm.watchdog.model=i6300esb
+# The model of Watchdog timer to present to the Guest
+# For all models refer to the libvirt documentation.
+# Recommend value is: i6300esb
+#
+# vm.watchdog.action=none
+# Action to take when the Guest/Instance is no longer notifiying the Watchdog
+# timer.
+# For all actions refer to the libvirt documentation.
+# Recommended values are: none, reset and poweroff.
diff --git a/agent/pom.xml b/agent/pom.xml
index 5837450ddf0..3ee1c5dbacb 100644
--- a/agent/pom.xml
+++ b/agent/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
diff --git a/agent/src/com/cloud/agent/Agent.java b/agent/src/com/cloud/agent/Agent.java
index 7fab5f4d301..7e802205f5c 100644
--- a/agent/src/com/cloud/agent/Agent.java
+++ b/agent/src/com/cloud/agent/Agent.java
@@ -16,12 +16,14 @@
// under the License.
package com.cloud.agent;
+import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.channels.ClosedChannelException;
+import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -35,7 +37,13 @@
import javax.naming.ConfigurationException;
+import org.apache.cloudstack.ca.SetupCertificateAnswer;
+import org.apache.cloudstack.ca.SetupCertificateCommand;
+import org.apache.cloudstack.ca.SetupKeyStoreCommand;
+import org.apache.cloudstack.ca.SetupKeystoreAnswer;
import org.apache.cloudstack.managed.context.ManagedContextTimerTask;
+import org.apache.cloudstack.utils.security.KeyStoreUtils;
+import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.slf4j.MDC;
@@ -68,6 +76,7 @@
import com.cloud.utils.nio.Task;
import com.cloud.utils.script.OutputInterpreter;
import com.cloud.utils.script.Script;
+import com.google.common.base.Strings;
/**
* @config
@@ -126,6 +135,9 @@ public int value() {
private final ThreadPoolExecutor _ugentTaskPool;
ExecutorService _executor;
+ private String _keystoreSetupPath;
+ private String _keystoreCertImportPath;
+
// for simulator use only
public Agent(final IAgentShell shell) {
_shell = shell;
@@ -166,7 +178,8 @@ public Agent(final IAgentShell shell, final int localAgentId, final ServerResour
throw new ConfigurationException("Unable to configure " + _resource.getName());
}
- _connection = new NioClient("Agent", _shell.getHost(), _shell.getPort(), _shell.getWorkers(), this);
+ final String host = _shell.getHost();
+ _connection = new NioClient("Agent", host, _shell.getPort(), _shell.getWorkers(), this);
// ((NioClient)_connection).setBindAddress(_shell.getPrivateIp());
@@ -182,7 +195,7 @@ public Agent(final IAgentShell shell, final int localAgentId, final ServerResour
"agentRequest-Handler"));
s_logger.info("Agent [id = " + (_id != null ? _id : "new") + " : type = " + getResourceName() + " : zone = " + _shell.getZone() + " : pod = " + _shell.getPod() +
- " : workers = " + _shell.getWorkers() + " : host = " + _shell.getHost() + " : port = " + _shell.getPort());
+ " : workers = " + _shell.getWorkers() + " : host = " + host + " : port = " + _shell.getPort());
}
public String getVersion() {
@@ -224,6 +237,16 @@ public void start() {
throw new CloudRuntimeException("Unable to start the resource: " + _resource.getName());
}
+ _keystoreSetupPath = Script.findScript("scripts/util/", KeyStoreUtils.keyStoreSetupScript);
+ if (_keystoreSetupPath == null) {
+ throw new CloudRuntimeException(String.format("Unable to find the '%s' script", KeyStoreUtils.keyStoreSetupScript));
+ }
+
+ _keystoreCertImportPath = Script.findScript("scripts/util/", KeyStoreUtils.keyStoreImportScript);
+ if (_keystoreCertImportPath == null) {
+ throw new CloudRuntimeException(String.format("Unable to find the '%s' script", KeyStoreUtils.keyStoreImportScript));
+ }
+
try {
_connection.start();
} catch (final NioConnectionException e) {
@@ -231,8 +254,10 @@ public void start() {
s_logger.info("Attempted to connect to the server, but received an unexpected exception, trying again...");
}
while (!_connection.isStartup()) {
+ final String host = _shell.getHost();
_shell.getBackoffAlgorithm().waitBeforeRetry();
- _connection = new NioClient("Agent", _shell.getHost(), _shell.getPort(), _shell.getWorkers(), this);
+ _connection = new NioClient("Agent", host, _shell.getPort(), _shell.getWorkers(), this);
+ s_logger.info("Connecting to host:" + host);
try {
_connection.start();
} catch (final NioConnectionException e) {
@@ -408,14 +433,21 @@ protected void reconnect(final Link link) {
_shell.getBackoffAlgorithm().waitBeforeRetry();
}
- _connection = new NioClient("Agent", _shell.getHost(), _shell.getPort(), _shell.getWorkers(), this);
+ final String host = _shell.getHost();
do {
- s_logger.info("Reconnecting...");
+ _connection = new NioClient("Agent", host, _shell.getPort(), _shell.getWorkers(), this);
+ s_logger.info("Reconnecting to host:" + host);
try {
_connection.start();
} catch (final NioConnectionException e) {
s_logger.warn("NIO Connection Exception " + e);
s_logger.info("Attempted to connect to the server, but received an unexpected exception, trying again...");
+ _connection.stop();
+ try {
+ _connection.cleanUp();
+ } catch (final IOException ex) {
+ s_logger.warn("Fail to clean up old connection. " + ex);
+ }
}
_shell.getBackoffAlgorithm().waitBeforeRetry();
} while (!_connection.isStartup());
@@ -515,7 +547,10 @@ protected void processRequest(final Request request, final Link link) {
s_logger.warn("No handler found to process cmd: " + cmd.toString());
answer = new AgentControlAnswer(cmd);
}
-
+ } else if (cmd instanceof SetupKeyStoreCommand && ((SetupKeyStoreCommand) cmd).isHandleByAgent()) {
+ answer = setupAgentKeystore((SetupKeyStoreCommand) cmd);
+ } else if (cmd instanceof SetupCertificateCommand && ((SetupCertificateCommand) cmd).isHandleByAgent()) {
+ answer = setupAgentCertificate((SetupCertificateCommand) cmd);
} else {
if (cmd instanceof ReadyCommand) {
processReadyCommand(cmd);
@@ -565,6 +600,86 @@ protected void processRequest(final Request request, final Link link) {
}
}
+ public Answer setupAgentKeystore(final SetupKeyStoreCommand cmd) {
+ final String keyStorePassword = cmd.getKeystorePassword();
+ final long validityDays = cmd.getValidityDays();
+
+ s_logger.debug("Setting up agent keystore file and generating CSR");
+
+ final File agentFile = PropertiesUtil.findConfigFile("agent.properties");
+ if (agentFile == null) {
+ return new Answer(cmd, false, "Failed to find agent.properties file");
+ }
+ final String keyStoreFile = agentFile.getParent() + "/" + KeyStoreUtils.defaultKeystoreFile;
+ final String csrFile = agentFile.getParent() + "/" + KeyStoreUtils.defaultCsrFile;
+
+ String storedPassword = _shell.getPersistentProperty(null, KeyStoreUtils.passphrasePropertyName);
+ if (Strings.isNullOrEmpty(storedPassword)) {
+ storedPassword = keyStorePassword;
+ _shell.setPersistentProperty(null, KeyStoreUtils.passphrasePropertyName, storedPassword);
+ }
+
+ Script script = new Script(_keystoreSetupPath, 60000, s_logger);
+ script.add(agentFile.getAbsolutePath());
+ script.add(keyStoreFile);
+ script.add(storedPassword);
+ script.add(String.valueOf(validityDays));
+ script.add(csrFile);
+ String result = script.execute();
+ if (result != null) {
+ throw new CloudRuntimeException("Unable to setup keystore file");
+ }
+
+ final String csrString;
+ try {
+ csrString = FileUtils.readFileToString(new File(csrFile), Charset.defaultCharset());
+ } catch (IOException e) {
+ throw new CloudRuntimeException("Unable to read generated CSR file", e);
+ }
+ return new SetupKeystoreAnswer(csrString);
+ }
+
+ private Answer setupAgentCertificate(final SetupCertificateCommand cmd) {
+ final String certificate = cmd.getCertificate();
+ final String privateKey = cmd.getPrivateKey();
+ final String caCertificates = cmd.getCaCertificates();
+
+ s_logger.debug("Importing received certificate to agent's keystore");
+
+ final File agentFile = PropertiesUtil.findConfigFile("agent.properties");
+ if (agentFile == null) {
+ return new Answer(cmd, false, "Failed to find agent.properties file");
+ }
+ final String keyStoreFile = agentFile.getParent() + "/" + KeyStoreUtils.defaultKeystoreFile;
+ final String certFile = agentFile.getParent() + "/" + KeyStoreUtils.defaultCertFile;
+ final String privateKeyFile = agentFile.getParent() + "/" + KeyStoreUtils.defaultPrivateKeyFile;
+ final String caCertFile = agentFile.getParent() + "/" + KeyStoreUtils.defaultCaCertFile;
+
+ try {
+ FileUtils.writeStringToFile(new File(certFile), certificate, Charset.defaultCharset());
+ FileUtils.writeStringToFile(new File(caCertFile), caCertificates, Charset.defaultCharset());
+ s_logger.debug("Saved received client certificate to: " + certFile);
+ } catch (IOException e) {
+ throw new CloudRuntimeException("Unable to save received agent client and ca certificates", e);
+ }
+
+ Script script = new Script(_keystoreCertImportPath, 60000, s_logger);
+ script.add(agentFile.getAbsolutePath());
+ script.add(keyStoreFile);
+ script.add(KeyStoreUtils.agentMode);
+ script.add(certFile);
+ script.add("");
+ script.add(caCertFile);
+ script.add("");
+ script.add(privateKeyFile);
+ script.add(privateKey);
+ String result = script.execute();
+ if (result != null) {
+ throw new CloudRuntimeException("Unable to import certificate into keystore file");
+ }
+ return new SetupCertificateAnswer(true);
+ }
+
public void processResponse(final Response response, final Link link) {
final Answer answer = response.getAnswer();
if (s_logger.isDebugEnabled()) {
diff --git a/agent/src/com/cloud/agent/AgentShell.java b/agent/src/com/cloud/agent/AgentShell.java
index 5e0da68c6d6..5950bc78e61 100644
--- a/agent/src/com/cloud/agent/AgentShell.java
+++ b/agent/src/com/cloud/agent/AgentShell.java
@@ -67,6 +67,7 @@
private int _proxyPort;
private int _workers;
private String _guid;
+ private int _hostCounter = 0;
private int _nextAgentId = 1;
private volatile boolean _exit = false;
private int _pingRetries;
@@ -107,7 +108,17 @@ public String getPod() {
@Override
public String getHost() {
- return _host;
+ final String[] hosts = _host.split(",");
+ if (_hostCounter >= hosts.length) {
+ _hostCounter = 0;
+ }
+ final String host = hosts[_hostCounter % hosts.length];
+ _hostCounter++;
+ return host;
+ }
+
+ public void setHost(final String host) {
+ _host = host;
}
@Override
diff --git a/agent/src/com/cloud/agent/dao/impl/PropertiesStorage.java b/agent/src/com/cloud/agent/dao/impl/PropertiesStorage.java
index df1b1ea7b27..e9eac645cb7 100644
--- a/agent/src/com/cloud/agent/dao/impl/PropertiesStorage.java
+++ b/agent/src/com/cloud/agent/dao/impl/PropertiesStorage.java
@@ -51,6 +51,9 @@ public synchronized String get(String key) {
@Override
public synchronized void persist(String key, String value) {
+ if (!loadFromFile(_file)) {
+ s_logger.error("Failed to load changes and then write to them");
+ }
_properties.setProperty(key, value);
FileOutputStream output = null;
try {
@@ -65,6 +68,20 @@ public synchronized void persist(String key, String value) {
}
}
+ private synchronized boolean loadFromFile(final File file) {
+ try {
+ PropertiesUtil.loadFromFile(_properties, file);
+ _file = file;
+ } catch (FileNotFoundException e) {
+ s_logger.error("How did we get here? ", e);
+ return false;
+ } catch (IOException e) {
+ s_logger.error("IOException: ", e);
+ return false;
+ }
+ return true;
+ }
+
@Override
public synchronized boolean configure(String name, Map<String, Object> params) {
_name = name;
@@ -86,17 +103,7 @@ public synchronized boolean configure(String name, Map<String, Object> params) {
return false;
}
}
- try {
- PropertiesUtil.loadFromFile(_properties, file);
- _file = file;
- } catch (FileNotFoundException e) {
- s_logger.error("How did we get here? ", e);
- return false;
- } catch (IOException e) {
- s_logger.error("IOException: ", e);
- return false;
- }
- return true;
+ return loadFromFile(file);
}
@Override
diff --git a/agent/src/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java b/agent/src/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java
index 08f09823986..1fed3be753c 100644
--- a/agent/src/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java
+++ b/agent/src/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java
@@ -32,11 +32,8 @@
import javax.naming.ConfigurationException;
-import org.apache.log4j.Logger;
-
-import com.google.gson.Gson;
-
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
+import org.apache.log4j.Logger;
import com.cloud.agent.Agent.ExitStatus;
import com.cloud.agent.api.AgentControlAnswer;
@@ -64,6 +61,7 @@
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.net.NetUtils;
import com.cloud.utils.script.Script;
+import com.google.gson.Gson;
/**
*
@@ -240,9 +238,11 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
_proxyVmId = NumbersUtil.parseLong(value, 0);
if (_localgw != null) {
- String mgmtHost = (String)params.get("host");
+ String mgmtHosts = (String)params.get("host");
if (_eth1ip != null) {
- addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, mgmtHost);
+ for (final String mgmtHost : mgmtHosts.split(",")) {
+ addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, mgmtHost);
+ }
String internalDns1 = (String) params.get("internaldns1");
if (internalDns1 == null) {
s_logger.warn("No DNS entry found during configuration of NfsSecondaryStorage");
diff --git a/agent/test/com/cloud/agent/AgentShellTest.java b/agent/test/com/cloud/agent/AgentShellTest.java
index 5baa7bf800e..8ceba4531d1 100644
--- a/agent/test/com/cloud/agent/AgentShellTest.java
+++ b/agent/test/com/cloud/agent/AgentShellTest.java
@@ -16,6 +16,8 @@
// under the License.
package com.cloud.agent;
+import java.util.Arrays;
+import java.util.List;
import java.util.UUID;
import javax.naming.ConfigurationException;
@@ -23,6 +25,8 @@
import org.junit.Assert;
import org.junit.Test;
+import com.cloud.utils.StringUtils;
+
public class AgentShellTest {
@Test
public void parseCommand() throws ConfigurationException {
@@ -44,4 +48,15 @@ public void loadProperties() throws ConfigurationException {
Assert.assertNotNull(shell.getProperties());
Assert.assertFalse(shell.getProperties().entrySet().isEmpty());
}
+
+ @Test
+ public void testGetHost() {
+ AgentShell shell = new AgentShell();
+ List<String> hosts = Arrays.asList("10.1.1.1", "20.2.2.2", "30.3.3.3", "2001:db8::1");
+ shell.setHost(StringUtils.listToCsvTags(hosts));
+ for (String host : hosts) {
+ Assert.assertEquals(host, shell.getHost());
+ }
+ Assert.assertEquals(shell.getHost(), hosts.get(0));
+ }
}
diff --git a/api/pom.xml b/api/pom.xml
index cdf6d54884c..6352e117bfe 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
@@ -51,6 +51,11 @@
<artifactId>cloud-framework-config</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-framework-ca</artifactId>
+ <version>${project.version}</version>
+ </dependency>
</dependencies>
<build>
<plugins>
diff --git a/api/src/com/cloud/agent/api/to/LoadBalancerTO.java b/api/src/com/cloud/agent/api/to/LoadBalancerTO.java
index 4d5a2c05db0..3a3dfa47502 100644
--- a/api/src/com/cloud/agent/api/to/LoadBalancerTO.java
+++ b/api/src/com/cloud/agent/api/to/LoadBalancerTO.java
@@ -45,6 +45,10 @@
boolean revoked;
boolean alreadyAdded;
boolean inline;
+ String srcIpVlan;
+ String srcIpGateway;
+ String srcIpNetmask;
+ Long networkId;
DestinationTO[] destinations;
private StickinessPolicyTO[] stickinessPolicies;
private HealthCheckPolicyTO[] healthCheckPolicies;
@@ -82,6 +86,15 @@ public LoadBalancerTO(String id, String srcIp, int srcPort, String protocol, Str
this(id, srcIp, srcPort, protocol, algorithm, revoked, alreadyAdded, inline, argDestinations, stickinessPolicies, null, null, null);
}
+ public LoadBalancerTO(String id, List<DestinationTO> destinations) {
+ this.uuid = id;
+ int i = 0;
+ this.destinations = new DestinationTO[destinations.size()];
+ for (DestinationTO destination : destinations) {
+ this.destinations[i++] = new DestinationTO(destination.getDestIp(), destination.getDestPort(), destination.getMonitorState());
+ }
+ }
+
public LoadBalancerTO(String id, String srcIp, int srcPort, String protocol, String algorithm, boolean revoked, boolean alreadyAdded, boolean inline,
List<LbDestination> argDestinations, List<LbStickinessPolicy> stickinessPolicies, List<LbHealthCheckPolicy> healthCheckPolicies, LbSslCert sslCert,
String lbProtocol) {
@@ -194,21 +207,53 @@ public LbSslCert getSslCert() {
return this.sslCert;
}
+ public String getSrcIpVlan() {
+ return srcIpVlan;
+ }
+
+ public void setSrcIpVlan(String srcIpVlan) {
+ this.srcIpVlan = srcIpVlan;
+ }
+
+ public Long getNetworkId() {
+ return networkId;
+ }
+
+ public void setNetworkId(long id) {
+ this.networkId = id;
+ }
+
+ public String getSrcIpGateway() {
+ return srcIpGateway;
+ }
+
+ public void setSrcIpGateway(String srcIpGateway) {
+ this.srcIpGateway = srcIpGateway;
+ }
+
+ public String getSrcIpNetmask() {
+ return srcIpNetmask;
+ }
+
+ public void setSrcIpNetmask(String srcIpNetmask) {
+ this.srcIpNetmask = srcIpNetmask;
+ }
+
public static class StickinessPolicyTO {
- private String _methodName;
- private List<Pair<String, String>> _paramsList;
+ private String methodName;
+ private List<Pair<String, String>> params;
public String getMethodName() {
- return _methodName;
+ return methodName;
}
public List<Pair<String, String>> getParams() {
- return _paramsList;
+ return params;
}
public StickinessPolicyTO(String methodName, List<Pair<String, String>> paramsList) {
- this._methodName = methodName;
- this._paramsList = paramsList;
+ this.methodName = methodName;
+ this.params = paramsList;
}
}
@@ -219,7 +264,7 @@ public StickinessPolicyTO(String methodName, List<Pair<String, String>> paramsLi
private int healthcheckInterval;
private int healthcheckThresshold;
private int unhealthThresshold;
- private boolean revoke = false;
+ private boolean revoked = false;
public HealthCheckPolicyTO(String pingPath, String description, int responseTime, int healthcheckInterval, int healthcheckThresshold, int unhealthThresshold,
boolean revoke) {
@@ -230,7 +275,7 @@ public HealthCheckPolicyTO(String pingPath, String description, int responseTime
this.healthcheckInterval = healthcheckInterval;
this.healthcheckThresshold = healthcheckThresshold;
this.unhealthThresshold = unhealthThresshold;
- this.revoke = revoke;
+ this.revoked = revoke;
}
public HealthCheckPolicyTO() {
@@ -262,11 +307,11 @@ public int getUnhealthThresshold() {
}
public void setRevoke(boolean revoke) {
- this.revoke = revoke;
+ this.revoked = revoke;
}
public boolean isRevoked() {
- return revoke;
+ return revoked;
}
}
@@ -285,6 +330,12 @@ public DestinationTO(String destIp, int destPort, boolean revoked, boolean alrea
this.alreadyAdded = alreadyAdded;
}
+ public DestinationTO(String destIp, int destPort, String monitorState) {
+ this.destIp = destIp;
+ this.destPort = destPort;
+ this.monitorState = monitorState;
+ }
+
protected DestinationTO() {
}
diff --git a/api/src/com/cloud/agent/api/to/NicTO.java b/api/src/com/cloud/agent/api/to/NicTO.java
index bd681f282cd..3863e1bafe7 100644
--- a/api/src/com/cloud/agent/api/to/NicTO.java
+++ b/api/src/com/cloud/agent/api/to/NicTO.java
@@ -16,7 +16,10 @@
// under the License.
package com.cloud.agent.api.to;
+import com.cloud.offering.NetworkOffering;
+
import java.util.List;
+import java.util.Map;
public class NicTO extends NetworkTO {
int deviceId;
@@ -26,6 +29,7 @@
boolean pxeDisable;
String nicUuid;
List<String> nicSecIps;
+ Map<NetworkOffering.Detail, String> details;
public NicTO() {
super();
@@ -97,4 +101,12 @@ public String getNetworkUuid() {
public void setNetworkUuid(String uuid) {
super.setUuid(uuid);
}
+
+ public Map<NetworkOffering.Detail, String> getDetails() {
+ return details;
+ }
+
+ public void setDetails(final Map<NetworkOffering.Detail, String> details) {
+ this.details = details;
+ }
}
diff --git a/api/src/com/cloud/capacity/Capacity.java b/api/src/com/cloud/capacity/Capacity.java
index 2fbc1d6eef1..ba04a82a5de 100644
--- a/api/src/com/cloud/capacity/Capacity.java
+++ b/api/src/com/cloud/capacity/Capacity.java
@@ -32,6 +32,8 @@
public static final short CAPACITY_TYPE_LOCAL_STORAGE = 9;
public static final short CAPACITY_TYPE_GPU = 19;
+ public static final short CAPACITY_TYPE_CPU_CORE = 90;
+
public Long getHostOrPoolId();
public Long getDataCenterId();
@@ -49,4 +51,6 @@
public long getReservedCapacity();
public Float getUsedPercentage();
+
+ public Long getAllocatedCapacity();
}
diff --git a/api/src/com/cloud/dc/DataCenter.java b/api/src/com/cloud/dc/DataCenter.java
index 5b3d3c01f30..7d434c5f231 100644
--- a/api/src/com/cloud/dc/DataCenter.java
+++ b/api/src/com/cloud/dc/DataCenter.java
@@ -18,15 +18,14 @@
import com.cloud.org.Grouping;
import org.apache.cloudstack.acl.InfrastructureEntity;
-import org.apache.cloudstack.api.Identity;
-import org.apache.cloudstack.api.InternalIdentity;
+import org.apache.cloudstack.kernel.Partition;
import java.util.Map;
/**
*
*/
-public interface DataCenter extends InfrastructureEntity, Grouping, Identity, InternalIdentity {
+public interface DataCenter extends InfrastructureEntity, Grouping, Partition {
public enum NetworkType {
Basic, Advanced,
diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java
index 3cc4eac81f1..ec3f3ac6d10 100644
--- a/api/src/com/cloud/event/EventTypes.java
+++ b/api/src/com/cloud/event/EventTypes.java
@@ -16,6 +16,9 @@
// under the License.
package com.cloud.event;
+import java.util.HashMap;
+import java.util.Map;
+
import com.cloud.dc.DataCenter;
import com.cloud.dc.Pod;
import com.cloud.dc.StorageNetworkIpRange;
@@ -54,10 +57,10 @@
import com.cloud.offering.ServiceOffering;
import com.cloud.projects.Project;
import com.cloud.server.ResourceTag;
-import com.cloud.storage.StoragePool;
import com.cloud.storage.GuestOS;
import com.cloud.storage.GuestOSHypervisor;
import com.cloud.storage.Snapshot;
+import com.cloud.storage.StoragePool;
import com.cloud.storage.Volume;
import com.cloud.storage.snapshot.SnapshotPolicy;
import com.cloud.template.VirtualMachineTemplate;
@@ -68,12 +71,11 @@
import com.cloud.vm.VirtualMachine;
import org.apache.cloudstack.acl.Role;
import org.apache.cloudstack.acl.RolePermission;
+import org.apache.cloudstack.annotation.Annotation;
import org.apache.cloudstack.config.Configuration;
+import org.apache.cloudstack.ha.HAConfig;
import org.apache.cloudstack.usage.Usage;
-import java.util.HashMap;
-import java.util.Map;
-
public class EventTypes {
//map of Event and corresponding entity for which Event is applicable
@@ -176,6 +178,11 @@
public static final String EVENT_ROLE_PERMISSION_UPDATE = "ROLE.PERMISSION.UPDATE";
public static final String EVENT_ROLE_PERMISSION_DELETE = "ROLE.PERMISSION.DELETE";
+ // CA events
+ public static final String EVENT_CA_CERTIFICATE_ISSUE = "CA.CERTIFICATE.ISSUE";
+ public static final String EVENT_CA_CERTIFICATE_REVOKE = "CA.CERTIFICATE.REVOKE";
+ public static final String EVENT_CA_CERTIFICATE_PROVISION = "CA.CERTIFICATE.PROVISION";
+
// Account events
public static final String EVENT_ACCOUNT_ENABLE = "ACCOUNT.ENABLE";
public static final String EVENT_ACCOUNT_DISABLE = "ACCOUNT.DISABLE";
@@ -317,6 +324,12 @@
public static final String EVENT_HOST_OUTOFBAND_MANAGEMENT_CHANGE_PASSWORD = "HOST.OOBM.CHANGEPASSWORD";
public static final String EVENT_HOST_OUTOFBAND_MANAGEMENT_POWERSTATE_TRANSITION = "HOST.OOBM.POWERSTATE.TRANSITION";
+ // HA
+ public static final String EVENT_HA_RESOURCE_ENABLE = "HA.RESOURCE.ENABLE";
+ public static final String EVENT_HA_RESOURCE_DISABLE = "HA.RESOURCE.DISABLE";
+ public static final String EVENT_HA_RESOURCE_CONFIGURE = "HA.RESOURCE.CONFIGURE";
+ public static final String EVENT_HA_STATE_TRANSITION = "HA.STATE.TRANSITION";
+
// Maintenance
public static final String EVENT_MAINTENANCE_CANCEL = "MAINT.CANCEL";
public static final String EVENT_MAINTENANCE_CANCEL_PRIMARY_STORAGE = "MAINT.CANCEL.PS";
@@ -391,6 +404,10 @@
public static final String EVENT_EXTERNAL_LB_DEVICE_DELETE = "PHYSICAL.LOADBALANCER.DELETE";
public static final String EVENT_EXTERNAL_LB_DEVICE_CONFIGURE = "PHYSICAL.LOADBALANCER.CONFIGURE";
+ // external NCC device events
+ public static final String EVENT_EXTERNAL_NCC_DEVICE_ADD = "PHYSICAL.NCC.ADD";
+ public static final String EVENT_EXTERNAL_NCC_DEVICE_DELETE = "PHYSICAL.NCC.DELETE";
+
// external switch management device events (E.g.: Cisco Nexus 1000v Virtual Supervisor Module.
public static final String EVENT_EXTERNAL_SWITCH_MGMT_DEVICE_ADD = "SWITCH.MGMT.ADD";
public static final String EVENT_EXTERNAL_SWITCH_MGMT_DEVICE_DELETE = "SWITCH.MGMT.DELETE";
@@ -545,6 +562,17 @@
//Usage related events
public static final String EVENT_USAGE_REMOVE_USAGE_RECORDS = "USAGE.REMOVE.USAGE.RECORDS";
+ // Netscaler Service Package events
+ public static final String EVENT_NETSCALER_SERVICEPACKAGE_ADD = "NETSCALER.SERVICEPACKAGE.ADD";
+ public static final String EVENT_NETSCALER_SERVICEPACKAGE_DELETE = "NETSCALER.SERVICEPACKAGE.DELETE";
+
+ public static final String EVENT_NETSCALER_VM_START = "NETSCALERVM.START";
+ public static final String EVENT_NETSCALER_VM_STOP = "NETSCALERVM.STOP";
+
+ public static final String EVENT_ANNOTATION_CREATE = "ANNOTATION.CREATE";
+ public static final String EVENT_ANNOTATION_REMOVE = "ANNOTATION.REMOVE";
+
+
static {
// TODO: need a way to force author adding event types to declare the entity details as well, with out braking
@@ -761,6 +789,12 @@
entityEventDetails.put(EVENT_HOST_OUTOFBAND_MANAGEMENT_CHANGE_PASSWORD, Host.class);
entityEventDetails.put(EVENT_HOST_OUTOFBAND_MANAGEMENT_POWERSTATE_TRANSITION, Host.class);
+ // HA
+ entityEventDetails.put(EVENT_HA_RESOURCE_ENABLE, HAConfig.class);
+ entityEventDetails.put(EVENT_HA_RESOURCE_DISABLE, HAConfig.class);
+ entityEventDetails.put(EVENT_HA_RESOURCE_CONFIGURE, HAConfig.class);
+ entityEventDetails.put(EVENT_HA_STATE_TRANSITION, HAConfig.class);
+
// Maintenance
entityEventDetails.put(EVENT_MAINTENANCE_CANCEL, Host.class);
entityEventDetails.put(EVENT_MAINTENANCE_CANCEL_PRIMARY_STORAGE, Host.class);
@@ -918,6 +952,12 @@
//Usage
entityEventDetails.put(EVENT_USAGE_REMOVE_USAGE_RECORDS, Usage.class);
+ // Netscaler Service Packages
+ entityEventDetails.put(EVENT_NETSCALER_SERVICEPACKAGE_ADD, "NETSCALER.SERVICEPACKAGE.CREATE");
+ entityEventDetails.put(EVENT_NETSCALER_SERVICEPACKAGE_DELETE, "NETSCALER.SERVICEPACKAGE.DELETE");
+
+ entityEventDetails.put(EVENT_ANNOTATION_CREATE, Annotation.class);
+ entityEventDetails.put(EVENT_ANNOTATION_REMOVE, Annotation.class);
}
public static String getEntityForEvent(String eventName) {
diff --git a/api/src/com/cloud/host/Host.java b/api/src/com/cloud/host/Host.java
index 689ed12b64e..1ecd48d74ce 100644
--- a/api/src/com/cloud/host/Host.java
+++ b/api/src/com/cloud/host/Host.java
@@ -16,22 +16,22 @@
// under the License.
package com.cloud.host;
-import java.util.Date;
-
-import org.apache.cloudstack.api.Identity;
-import org.apache.cloudstack.api.InternalIdentity;
-
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.resource.ResourceState;
import com.cloud.utils.fsm.StateObject;
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.ha.HAResource;
+import org.apache.cloudstack.kernel.Partition;
+
+import java.util.Date;
/**
* Host represents one particular host server.
*/
-public interface Host extends StateObject<Status>, Identity, InternalIdentity {
+public interface Host extends StateObject<Status>, Identity, Partition, HAResource {
public enum Type {
Storage(false), Routing(false), SecondaryStorage(false), SecondaryStorageCmdExecutor(false), ConsoleProxy(true), ExternalFirewall(false), ExternalLoadBalancer(
- false), ExternalVirtualSwitchSupervisor(false), PxeServer(false), BaremetalPxe(false), BaremetalDhcp(false), TrafficMonitor(false),
+ false), ExternalVirtualSwitchSupervisor(false), PxeServer(false), BaremetalPxe(false), BaremetalDhcp(false), TrafficMonitor(false), NetScalerControlCenter(false),
ExternalDhcp(false), SecondaryStorageVM(true), LocalSecondaryStorage(false), L2Networking(false);
boolean _virtual;
@@ -202,5 +202,7 @@ public boolean isVirtual() {
boolean isInMaintenanceStates();
+ boolean isDisabled();
+
ResourceState getResourceState();
}
diff --git a/api/src/com/cloud/host/Status.java b/api/src/com/cloud/host/Status.java
index 73e6cc9185a..e381115db41 100644
--- a/api/src/com/cloud/host/Status.java
+++ b/api/src/com/cloud/host/Status.java
@@ -150,12 +150,14 @@ public Status getNextStatus(Event e) throws NoTransitionException {
s_fsm.addTransition(Status.Down, Event.ManagementServerDown, Status.Down);
s_fsm.addTransition(Status.Down, Event.AgentDisconnected, Status.Down);
s_fsm.addTransition(Status.Down, Event.PingTimeout, Status.Down);
+ s_fsm.addTransition(Status.Down, Event.HostDown, Status.Down);
s_fsm.addTransition(Status.Alert, Event.AgentConnected, Status.Connecting);
s_fsm.addTransition(Status.Alert, Event.Ping, Status.Up);
s_fsm.addTransition(Status.Alert, Event.Remove, Status.Removed);
s_fsm.addTransition(Status.Alert, Event.ManagementServerDown, Status.Alert);
s_fsm.addTransition(Status.Alert, Event.AgentDisconnected, Status.Alert);
s_fsm.addTransition(Status.Alert, Event.ShutdownRequested, Status.Disconnected);
+ s_fsm.addTransition(Status.Alert, Event.HostDown, Status.Down);
s_fsm.addTransition(Status.Rebalancing, Event.RebalanceFailed, Status.Disconnected);
s_fsm.addTransition(Status.Rebalancing, Event.RebalanceCompleted, Status.Connecting);
s_fsm.addTransition(Status.Rebalancing, Event.ManagementServerDown, Status.Disconnected);
diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java
index 122ce708327..2cd41494244 100644
--- a/api/src/com/cloud/network/Network.java
+++ b/api/src/com/cloud/network/Network.java
@@ -277,12 +277,26 @@ private State(String description) {
public class IpAddresses {
private String ip4Address;
private String ip6Address;
+ private String macAddress;
+
+ public String getMacAddress() {
+ return macAddress;
+ }
+
+ public void setMacAddress(String macAddress) {
+ this.macAddress = macAddress;
+ }
public IpAddresses(String ip4Address, String ip6Address) {
setIp4Address(ip4Address);
setIp6Address(ip6Address);
}
+ public IpAddresses(String ipAddress, String ip6Address, String macAddress) {
+ this(ipAddress, ip6Address);
+ setMacAddress(macAddress);
+ }
+
public String getIp4Address() {
return ip4Address;
}
diff --git a/api/src/com/cloud/network/NetworkModel.java b/api/src/com/cloud/network/NetworkModel.java
index 811c792a0ff..220fa99467f 100644
--- a/api/src/com/cloud/network/NetworkModel.java
+++ b/api/src/com/cloud/network/NetworkModel.java
@@ -27,6 +27,7 @@
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network.Capability;
+import com.cloud.network.Network.IpAddresses;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.Networks.TrafficType;
@@ -260,7 +261,7 @@
void checkIp6Parameters(String startIPv6, String endIPv6, String ip6Gateway, String ip6Cidr) throws InvalidParameterValueException;
- void checkRequestedIpAddresses(long networkId, String ip4, String ip6) throws InvalidParameterValueException;
+ void checkRequestedIpAddresses(long networkId, IpAddresses ips) throws InvalidParameterValueException;
String getStartIpv6Address(long id);
@@ -287,4 +288,6 @@
List<String[]> generateVmData(String userData, String serviceOffering, String zoneName,
String vmName, long vmId, String publicKey, String password, Boolean isWindows);
+ String getValidNetworkCidr(Network guestNetwork);
+
}
diff --git a/api/src/com/cloud/network/NetworkService.java b/api/src/com/cloud/network/NetworkService.java
index 598b77fc5e3..0ad42b5acdd 100644
--- a/api/src/com/cloud/network/NetworkService.java
+++ b/api/src/com/cloud/network/NetworkService.java
@@ -19,6 +19,7 @@
import java.util.List;
import java.util.Map;
+import org.apache.cloudstack.api.command.admin.address.ReleasePodIpCmdByAdmin;
import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd;
import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd;
import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd;
@@ -26,6 +27,7 @@
import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd;
import org.apache.cloudstack.api.command.user.vm.ListNicsCmd;
+import org.apache.cloudstack.api.response.AcquirePodIpCmdResponse;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException;
@@ -38,6 +40,7 @@
import com.cloud.user.Account;
import com.cloud.user.User;
import com.cloud.utils.Pair;
+import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.Nic;
import com.cloud.vm.NicSecondaryIp;
@@ -182,4 +185,8 @@ Network createPrivateNetwork(String networkName, String displayText, long physic
boolean configureNicSecondaryIp(NicSecondaryIp secIp, boolean isZoneSgEnabled);
List<? extends NicSecondaryIp> listVmNicSecondaryIps(ListNicsCmd listNicsCmd);
+
+ AcquirePodIpCmdResponse allocatePodIp(Account account, String zoneId, String podId) throws ResourceAllocationException, ConcurrentOperationException;
+
+ boolean releasePodIp(ReleasePodIpCmdByAdmin ip) throws CloudRuntimeException;
}
diff --git a/api/src/com/cloud/network/Networks.java b/api/src/com/cloud/network/Networks.java
index f027cf9fe99..37746f0d0f7 100644
--- a/api/src/com/cloud/network/Networks.java
+++ b/api/src/com/cloud/network/Networks.java
@@ -75,6 +75,10 @@
throw new CloudRuntimeException("Unable to convert to broadcast URI: " + value);
}
}
+ @Override
+ public String getValueFrom(URI uri) {
+ return uri.getAuthority();
+ }
},
Vswitch("vs", String.class), LinkLocal(null, null), Vnet("vnet", Long.class), Storage("storage", Integer.class), Lswitch("lswitch", String.class) {
@Override
diff --git a/api/src/com/cloud/network/PhysicalNetwork.java b/api/src/com/cloud/network/PhysicalNetwork.java
index bdf098f3abb..48e416c4b46 100644
--- a/api/src/com/cloud/network/PhysicalNetwork.java
+++ b/api/src/com/cloud/network/PhysicalNetwork.java
@@ -16,12 +16,16 @@
// under the License.
package com.cloud.network;
-import java.util.List;
-
+import com.cloud.exception.CloudException;
+import com.cloud.utils.Pair;
+import com.cloud.utils.StringUtils;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
-import com.cloud.utils.Pair;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
/**
*
@@ -32,8 +36,101 @@
Disabled, Enabled;
}
- public enum IsolationMethod {
- VLAN, L3, GRE, STT, BCF_SEGMENT, MIDO, SSP, VXLAN, ODL, L3VPN, VSP, VCS;
+ public class IsolationMethod {
+ protected static final String UNKNOWN_PROVIDER = "Unknown";
+ static Set<IsolationMethod> registeredIsolationMethods = new HashSet<>();
+
+ String methodPrefix;
+ String provider;
+
+ public IsolationMethod(String prfx) {
+ this(prfx, UNKNOWN_PROVIDER);
+ }
+
+ public IsolationMethod(String prfx, String prvdr) {
+ methodPrefix = prfx;
+ provider = StringUtils.isNotBlank(prvdr)? prvdr : UNKNOWN_PROVIDER;
+ registeredIsolationMethods.add(this);
+ }
+
+ /**
+ * gets a IsolationMethod object that defines this prefix and if any it returns the first one found that has a known provider. If none has a known provider
+ * it will return the one with the unknown provider. if none is found it return null.
+ *
+ * @param prfx
+ * @return
+ */
+ public static IsolationMethod getIsolationMethod(String prfx) throws IsolationMethodNotRegistered {
+ IsolationMethod rc = null;
+ for (IsolationMethod method: registeredIsolationMethods) {
+ if (method.methodPrefix.equals(prfx)) {
+ rc = method;
+ if(! rc.getProvider().equals(UNKNOWN_PROVIDER)) {
+ break;
+ }
+ }
+ }
+ if (rc == null) {
+ throw new IsolationMethodNotRegistered("No registration of prefix '" + prfx + "' found.");
+ }
+ return rc;
+ }
+
+ public static IsolationMethod getIsolationMethod(String prfx, String provider) throws IsolationMethodNotRegistered {
+ for (IsolationMethod method: registeredIsolationMethods) {
+ if (method.methodPrefix.equals(prfx) && method.provider.equals(provider)) {
+ return method;
+ }
+ }
+ throw new IsolationMethodNotRegistered("No registration of prefix '" + prfx + "' for provider '" + provider + "' found.");
+ }
+
+ static class IsolationMethodNotRegistered extends CloudException {
+ IsolationMethodNotRegistered (String message) {
+ super(message);
+ }
+ }
+
+ public String getMethodPrefix() {
+ return methodPrefix;
+ }
+
+ public String getProvider() {
+ return provider;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ IsolationMethod that = (IsolationMethod)o;
+ return Objects.equals(methodPrefix, that.methodPrefix) && Objects.equals(provider, that.provider);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(methodPrefix, provider);
+ }
+
+ @Override
+ public String toString() {
+ return methodPrefix;
+ }
+
+ public static boolean remove(String prfx, String prvdr) {
+ prvdr = StringUtils.isNotBlank(prvdr)? prvdr : UNKNOWN_PROVIDER;
+
+ try {
+ return remove(getIsolationMethod(prfx, prvdr));
+ } catch (IsolationMethodNotRegistered isolationMethodNotRegistered) {
+ return false;
+ }
+ }
+ public static boolean remove(IsolationMethod method) {
+ return registeredIsolationMethods.remove(method);
+ }
}
public enum BroadcastDomainRange {
diff --git a/api/src/com/cloud/network/VirtualRouterProvider.java b/api/src/com/cloud/network/VirtualRouterProvider.java
index 8e2fa70d891..aca526b1832 100644
--- a/api/src/com/cloud/network/VirtualRouterProvider.java
+++ b/api/src/com/cloud/network/VirtualRouterProvider.java
@@ -21,7 +21,7 @@
public interface VirtualRouterProvider extends InternalIdentity, Identity {
public enum Type {
- VirtualRouter, ElasticLoadBalancerVm, VPCVirtualRouter, InternalLbVm
+ VirtualRouter, ElasticLoadBalancerVm, VPCVirtualRouter, InternalLbVm, NetScalerVm
}
public Type getType();
diff --git a/api/src/com/cloud/network/router/VirtualRouter.java b/api/src/com/cloud/network/router/VirtualRouter.java
index 060ef0fa141..84c85ce6675 100644
--- a/api/src/com/cloud/network/router/VirtualRouter.java
+++ b/api/src/com/cloud/network/router/VirtualRouter.java
@@ -23,7 +23,7 @@
*/
public interface VirtualRouter extends VirtualMachine {
public enum Role {
- VIRTUAL_ROUTER, LB, INTERNAL_LB_VM
+ VIRTUAL_ROUTER, LB, INTERNAL_LB_VM, NETSCALER_VM
}
public enum UpdateState {
diff --git a/api/src/com/cloud/network/rules/RulesService.java b/api/src/com/cloud/network/rules/RulesService.java
index 3eca14d6543..0b4afeef945 100644
--- a/api/src/com/cloud/network/rules/RulesService.java
+++ b/api/src/com/cloud/network/rules/RulesService.java
@@ -81,6 +81,6 @@
boolean disableStaticNat(long ipId) throws ResourceUnavailableException, NetworkRuleConflictException, InsufficientAddressCapacityException;
- PortForwardingRule updatePortForwardingRule(long id, Integer privatePort, Long virtualMachineId, Ip vmGuestIp, String customId, Boolean forDisplay);
+ PortForwardingRule updatePortForwardingRule(long id, Integer privatePort, Integer privateEndPort, Long virtualMachineId, Ip vmGuestIp, String customId, Boolean forDisplay);
}
diff --git a/api/src/com/cloud/offering/NetworkOffering.java b/api/src/com/cloud/offering/NetworkOffering.java
index 5eab98ab293..402846202e7 100644
--- a/api/src/com/cloud/offering/NetworkOffering.java
+++ b/api/src/com/cloud/offering/NetworkOffering.java
@@ -38,7 +38,7 @@
}
public enum Detail {
- InternalLbProvider, PublicLbProvider
+ InternalLbProvider, PublicLbProvider, servicepackageuuid, servicepackagedescription, PromiscuousMode, MacAddressChanges, ForgedTransmits
}
public final static String SystemPublicNetwork = "System-Public-Network";
@@ -133,4 +133,6 @@
boolean getSupportsStrechedL2();
boolean getSupportsPublicAccess();
+
+ String getServicePackage();
}
diff --git a/api/src/com/cloud/org/Cluster.java b/api/src/com/cloud/org/Cluster.java
index 90fcb5729e4..4079c88dfde 100644
--- a/api/src/com/cloud/org/Cluster.java
+++ b/api/src/com/cloud/org/Cluster.java
@@ -16,13 +16,11 @@
// under the License.
package com.cloud.org;
-import org.apache.cloudstack.api.Identity;
-import org.apache.cloudstack.api.InternalIdentity;
-
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.org.Managed.ManagedState;
+import org.apache.cloudstack.kernel.Partition;
-public interface Cluster extends Grouping, InternalIdentity, Identity {
+public interface Cluster extends Grouping, Partition {
public static enum ClusterType {
CloudManaged, ExternalManaged;
};
diff --git a/api/src/com/cloud/resource/ResourceState.java b/api/src/com/cloud/resource/ResourceState.java
index 5d2c962f989..d952afa0b7d 100644
--- a/api/src/com/cloud/resource/ResourceState.java
+++ b/api/src/com/cloud/resource/ResourceState.java
@@ -93,6 +93,7 @@ public ResourceState getNextState(Event a) {
s_fsm.addTransition(ResourceState.Enabled, Event.InternalCreated, ResourceState.Enabled);
s_fsm.addTransition(ResourceState.Enabled, Event.Disable, ResourceState.Disabled);
s_fsm.addTransition(ResourceState.Enabled, Event.AdminAskMaintenace, ResourceState.PrepareForMaintenance);
+ s_fsm.addTransition(ResourceState.Enabled, Event.InternalEnterMaintenance, ResourceState.Maintenance);
s_fsm.addTransition(ResourceState.Disabled, Event.Enable, ResourceState.Enabled);
s_fsm.addTransition(ResourceState.Disabled, Event.Disable, ResourceState.Disabled);
s_fsm.addTransition(ResourceState.Disabled, Event.InternalCreated, ResourceState.Disabled);
@@ -109,5 +110,7 @@ public ResourceState getNextState(Event a) {
s_fsm.addTransition(ResourceState.ErrorInMaintenance, Event.InternalEnterMaintenance, ResourceState.Maintenance);
s_fsm.addTransition(ResourceState.ErrorInMaintenance, Event.AdminCancelMaintenance, ResourceState.Enabled);
s_fsm.addTransition(ResourceState.Error, Event.InternalCreated, ResourceState.Error);
+ s_fsm.addTransition(ResourceState.Disabled, Event.DeleteHost, ResourceState.Disabled);
+
}
}
diff --git a/api/src/com/cloud/storage/ImageStore.java b/api/src/com/cloud/storage/ImageStore.java
index ec693c4e493..c019b17421d 100644
--- a/api/src/com/cloud/storage/ImageStore.java
+++ b/api/src/com/cloud/storage/ImageStore.java
@@ -41,4 +41,11 @@
* @return data store protocol
*/
String getProtocol();
+
+ /**
+ *
+ * @return uri
+ */
+ String getUrl();
+
}
diff --git a/api/src/com/cloud/storage/Snapshot.java b/api/src/com/cloud/storage/Snapshot.java
index 9e44e57e021..2f3a59541d9 100644
--- a/api/src/com/cloud/storage/Snapshot.java
+++ b/api/src/com/cloud/storage/Snapshot.java
@@ -79,6 +79,8 @@ public boolean equals(String status) {
String getName();
+ long getSnapshotId();
+
Date getCreated();
Type getRecurringType();
diff --git a/api/src/com/cloud/storage/VolumeApiService.java b/api/src/com/cloud/storage/VolumeApiService.java
index 673fffca7cd..d5a31d3365d 100644
--- a/api/src/com/cloud/storage/VolumeApiService.java
+++ b/api/src/com/cloud/storage/VolumeApiService.java
@@ -82,7 +82,7 @@
Volume detachVolumeFromVM(DetachVolumeCmd cmd);
- Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account, boolean quiescevm, Snapshot.LocationType locationType) throws ResourceAllocationException;
+ Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account, boolean quiescevm, Snapshot.LocationType locationType, boolean asyncBackup) throws ResourceAllocationException;
Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName, Snapshot.LocationType locationType) throws ResourceAllocationException;
diff --git a/api/src/com/cloud/user/ResourceLimitService.java b/api/src/com/cloud/user/ResourceLimitService.java
index fef16da942f..0ec2dc1c758 100644
--- a/api/src/com/cloud/user/ResourceLimitService.java
+++ b/api/src/com/cloud/user/ResourceLimitService.java
@@ -23,9 +23,13 @@
import com.cloud.configuration.ResourceLimit;
import com.cloud.domain.Domain;
import com.cloud.exception.ResourceAllocationException;
+import org.apache.cloudstack.framework.config.ConfigKey;
public interface ResourceLimitService {
+ static final ConfigKey<Long> ResourceCountCheckInterval = new ConfigKey<Long>("Advanced", Long.class, "resourcecount.check.interval", "300",
+ "Time (in seconds) to wait before retrying resource count check task. Default is 300, Setting this to 0 will not run the task", false);
+
/**
* Updates an existing resource limit with the specified details. If a limit doesn't exist, will create one.
*
diff --git a/api/src/com/cloud/user/User.java b/api/src/com/cloud/user/User.java
index 0ecdcfa58d4..c3ac66c6979 100644
--- a/api/src/com/cloud/user/User.java
+++ b/api/src/com/cloud/user/User.java
@@ -22,8 +22,9 @@
public interface User extends OwnedBy, InternalIdentity {
+ // UNKNOWN and NATIVE can be used interchangeably
public enum Source {
- LDAP, SAML2, SAML2DISABLED, UNKNOWN
+ LDAP, SAML2, SAML2DISABLED, UNKNOWN, NATIVE
}
public static final long UID_SYSTEM = 1;
diff --git a/api/src/com/cloud/vm/NicProfile.java b/api/src/com/cloud/vm/NicProfile.java
index 58e05124c89..6ef9cfe5db1 100644
--- a/api/src/com/cloud/vm/NicProfile.java
+++ b/api/src/com/cloud/vm/NicProfile.java
@@ -114,6 +114,11 @@ public NicProfile(String requestedIPv4, String requestedIPv6) {
this.requestedIPv6 = requestedIPv6;
}
+ public NicProfile(String requestedIPv4, String requestedIPv6, String requestedMacAddress) {
+ this(requestedIPv4, requestedIPv6);
+ this.macAddress = requestedMacAddress;
+ }
+
public NicProfile(ReservationStrategy strategy, String iPv4Address, String macAddress, String iPv4gateway, String iPv4netmask) {
format = AddressFormat.Ip4;
this.iPv4Address = iPv4Address;
diff --git a/api/src/com/cloud/vm/UserVmService.java b/api/src/com/cloud/vm/UserVmService.java
index db9ded89a98..68425c3b675 100644
--- a/api/src/com/cloud/vm/UserVmService.java
+++ b/api/src/com/cloud/vm/UserVmService.java
@@ -482,4 +482,8 @@ UserVm upgradeVirtualMachine(ScaleVMCmd cmd) throws ResourceUnavailableException
*/
public boolean isDisplayResourceEnabled(Long vmId);
+ void collectVmDiskStatistics(UserVm userVm);
+
+ void collectVmNetworkStatistics (UserVm userVm);
+
}
diff --git a/api/src/com/cloud/vm/VirtualMachine.java b/api/src/com/cloud/vm/VirtualMachine.java
index b45ac7c9be9..a46edd78f44 100644
--- a/api/src/com/cloud/vm/VirtualMachine.java
+++ b/api/src/com/cloud/vm/VirtualMachine.java
@@ -16,26 +16,24 @@
// under the License.
package com.cloud.vm;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.Map;
-
-import org.apache.cloudstack.acl.ControlledEntity;
-import org.apache.cloudstack.api.Displayable;
-import org.apache.cloudstack.api.Identity;
-import org.apache.cloudstack.api.InternalIdentity;
-
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.utils.fsm.StateMachine2;
import com.cloud.utils.fsm.StateMachine2.Transition;
import com.cloud.utils.fsm.StateMachine2.Transition.Impact;
import com.cloud.utils.fsm.StateObject;
+import org.apache.cloudstack.acl.ControlledEntity;
+import org.apache.cloudstack.api.Displayable;
+import org.apache.cloudstack.kernel.Partition;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Map;
/**
* VirtualMachine describes the properties held by a virtual machine
*
*/
-public interface VirtualMachine extends RunningOn, ControlledEntity, Identity, InternalIdentity, Displayable, StateObject<VirtualMachine.State> {
+public interface VirtualMachine extends RunningOn, ControlledEntity, Partition, Displayable, StateObject<VirtualMachine.State> {
public enum PowerState {
PowerUnknown,
@@ -214,6 +212,7 @@ public static boolean isVmDestroyed(State oldState, Event e, State newState) {
public enum Type {
User(false), DomainRouter(true), ConsoleProxy(true), SecondaryStorageVm(true), ElasticIpVm(true), ElasticLoadBalancerVm(true), InternalLoadBalancerVm(true),
+ NetScalerVm(true),
/*
* UserBareMetal is only used for selecting VirtualMachineGuru, there is no
diff --git a/api/src/com/cloud/vm/VmDetailConstants.java b/api/src/com/cloud/vm/VmDetailConstants.java
index c3c6db7a296..f24c4f587c4 100644
--- a/api/src/com/cloud/vm/VmDetailConstants.java
+++ b/api/src/com/cloud/vm/VmDetailConstants.java
@@ -24,4 +24,7 @@
public static final String HYPERVISOR_TOOLS_VERSION = "hypervisortoolsversion";
public static final String DATA_DISK_CONTROLLER = "dataDiskController";
public static final String SVGA_VRAM_SIZE = "svga.vramSize";
+ public static final String CPU_NUMBER = "cpuNumber";
+ public static final String CPU_SPEED = "cpuSpeed";
+ public static final String MEMORY = "memory";
}
diff --git a/api/src/com/cloud/vm/VmNetworkStats.java b/api/src/com/cloud/vm/VmNetworkStats.java
new file mode 100644
index 00000000000..7f96fdfdfac
--- /dev/null
+++ b/api/src/com/cloud/vm/VmNetworkStats.java
@@ -0,0 +1,26 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.vm;
+
+public interface VmNetworkStats {
+ // vm related network stats
+
+ public long getBytesSent();
+
+ public long getBytesReceived();
+
+}
diff --git a/api/src/org/apache/cloudstack/acl/RoleService.java b/api/src/org/apache/cloudstack/acl/RoleService.java
index 59eef51e782..98d170b5853 100644
--- a/api/src/org/apache/cloudstack/acl/RoleService.java
+++ b/api/src/org/apache/cloudstack/acl/RoleService.java
@@ -17,6 +17,7 @@
package org.apache.cloudstack.acl;
+import org.apache.cloudstack.acl.RolePermission.Permission;
import org.apache.cloudstack.framework.config.ConfigKey;
import java.util.List;
@@ -36,13 +37,14 @@
RolePermission findRolePermission(final Long id);
RolePermission findRolePermissionByUuid(final String uuid);
- RolePermission createRolePermission(final Role role, final Rule rule, final RolePermission.Permission permission, final String description);
+ RolePermission createRolePermission(final Role role, final Rule rule, final Permission permission, final String description);
/**
* updateRolePermission updates the order/position of an role permission
* @param role The role whose permissions needs to be re-ordered
* @param newOrder The new list of ordered role permissions
*/
boolean updateRolePermission(final Role role, final List<RolePermission> newOrder);
+ boolean updateRolePermission(final Role role, final RolePermission rolePermission, final Permission permission);
boolean deleteRolePermission(final RolePermission rolePermission);
List<Role> listRoles();
diff --git a/api/src/org/apache/cloudstack/alert/AlertService.java b/api/src/org/apache/cloudstack/alert/AlertService.java
index ad711ecea4e..26c3f3cf3ab 100644
--- a/api/src/org/apache/cloudstack/alert/AlertService.java
+++ b/api/src/org/apache/cloudstack/alert/AlertService.java
@@ -16,12 +16,12 @@
// under the License.
package org.apache.cloudstack.alert;
-import java.util.HashSet;
-import java.util.Set;
-
import com.cloud.capacity.Capacity;
import com.cloud.exception.InvalidParameterValueException;
+import java.util.HashSet;
+import java.util.Set;
+
public interface AlertService {
public static class AlertType {
private static Set<AlertType> defaultAlertTypes = new HashSet<AlertType>();
@@ -67,6 +67,8 @@ private AlertType(short type, String name, boolean isDefault) {
public static final AlertType ALERT_TYPE_SYNC = new AlertType((short)27, "ALERT.TYPE.SYNC", true);
public static final AlertType ALERT_TYPE_UPLOAD_FAILED = new AlertType((short)28, "ALERT.UPLOAD.FAILED", true);
public static final AlertType ALERT_TYPE_OOBM_AUTH_ERROR = new AlertType((short)29, "ALERT.OOBM.AUTHERROR", true);
+ public static final AlertType ALERT_TYPE_HA_ACTION = new AlertType((short)30, "ALERT.HA.ACTION", true);
+ public static final AlertType ALERT_TYPE_CA_CERT = new AlertType((short)31, "ALERT.CA.CERT", true);
public short getType() {
return type;
diff --git a/api/src/org/apache/cloudstack/annotation/Annotation.java b/api/src/org/apache/cloudstack/annotation/Annotation.java
new file mode 100644
index 00000000000..90e371e5071
--- /dev/null
+++ b/api/src/org/apache/cloudstack/annotation/Annotation.java
@@ -0,0 +1,37 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.annotation;
+
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.api.InternalIdentity;
+
+import java.util.Date;
+
+public interface Annotation extends InternalIdentity, Identity {
+
+ String getAnnotation();
+
+ String getEntityUuid();
+
+ AnnotationService.EntityType getEntityType();
+
+ String getUserUuid();
+
+ Date getCreated();
+
+ Date getRemoved();
+}
diff --git a/api/src/org/apache/cloudstack/annotation/AnnotationService.java b/api/src/org/apache/cloudstack/annotation/AnnotationService.java
new file mode 100644
index 00000000000..769a753b587
--- /dev/null
+++ b/api/src/org/apache/cloudstack/annotation/AnnotationService.java
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.annotation;
+
+import org.apache.cloudstack.api.command.admin.annotation.AddAnnotationCmd;
+import org.apache.cloudstack.api.command.admin.annotation.ListAnnotationsCmd;
+import org.apache.cloudstack.api.command.admin.annotation.RemoveAnnotationCmd;
+import org.apache.cloudstack.api.response.AnnotationResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+
+public interface AnnotationService {
+ ListResponse<AnnotationResponse> searchForAnnotations(ListAnnotationsCmd cmd);
+
+ AnnotationResponse addAnnotation(AddAnnotationCmd addAnnotationCmd);
+ AnnotationResponse addAnnotation(String text, EntityType type, String uuid);
+
+ AnnotationResponse removeAnnotation(RemoveAnnotationCmd removeAnnotationCmd);
+
+ enum EntityType {
+ HOST("host"), DOMAIN("domain"), VM("vm_instance");
+ private String tableName;
+
+ EntityType(String tableName) {
+ this.tableName = tableName;
+ }
+ static public boolean contains(String representation) {
+ try {
+ /* EntityType tiep = */ valueOf(representation);
+ return true;
+ } catch (IllegalArgumentException iae) {
+ return false;
+ }
+ }
+ }
+}
diff --git a/api/src/org/apache/cloudstack/api/APICommand.java b/api/src/org/apache/cloudstack/api/APICommand.java
index d451e4b10a3..c559be08116 100644
--- a/api/src/org/apache/cloudstack/api/APICommand.java
+++ b/api/src/org/apache/cloudstack/api/APICommand.java
@@ -16,8 +16,6 @@
// under the License.
package org.apache.cloudstack.api;
-import static java.lang.annotation.ElementType.TYPE;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@@ -25,9 +23,12 @@
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
+import static java.lang.annotation.ElementType.TYPE;
+
@Retention(RetentionPolicy.RUNTIME)
@Target({TYPE})
public @interface APICommand {
+
Class<? extends BaseResponse> responseObject();
String name() default "";
diff --git a/api/src/org/apache/cloudstack/api/AbstractGetUploadParamsCmd.java b/api/src/org/apache/cloudstack/api/AbstractGetUploadParamsCmd.java
index df63d747158..c82f4789367 100644
--- a/api/src/org/apache/cloudstack/api/AbstractGetUploadParamsCmd.java
+++ b/api/src/org/apache/cloudstack/api/AbstractGetUploadParamsCmd.java
@@ -18,15 +18,15 @@
*/
package org.apache.cloudstack.api;
+import java.net.URL;
+import java.util.UUID;
+
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.GetUploadParamsResponse;
import org.apache.cloudstack.api.response.ProjectResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.log4j.Logger;
-import java.net.URL;
-import java.util.UUID;
-
public abstract class AbstractGetUploadParamsCmd extends BaseCmd {
public static final Logger s_logger = Logger.getLogger(AbstractGetUploadParamsCmd.class.getName());
@@ -42,7 +42,7 @@
+ "to be hosted on")
private Long zoneId;
- @Parameter(name = ApiConstants.CHECKSUM, type = CommandType.STRING, description = "the MD5 checksum value of this volume/template")
+ @Parameter(name = ApiConstants.CHECKSUM, type = CommandType.STRING, description = "the checksum value of this volume/template " + ApiConstants.CHECKSUM_PARAMETER_PREFIX_DESCRIPTION)
private String checksum;
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "an optional accountName. Must be used with domainId.")
diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java
index a16a327bae0..1ec340df1e8 100644
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -21,10 +21,13 @@
public static final String ACCOUNTS = "accounts";
public static final String ACCOUNT_TYPE = "accounttype";
public static final String ACCOUNT_ID = "accountid";
+ public static final String ACTIVITY = "activity";
public static final String ADDRESS = "address";
public static final String ALGORITHM = "algorithm";
public static final String ALLOCATED_ONLY = "allocatedonly";
+ public static final String ANNOTATION = "annotation";
public static final String API_KEY = "apikey";
+ public static final String ASYNC_BACKUP = "asyncbackup";
public static final String USER_API_KEY = "userapikey";
public static final String APPLIED = "applied";
public static final String LIST_LB_VMIPS = "lbvmips";
@@ -35,12 +38,15 @@
public static final String BIND_PASSWORD = "bindpass";
public static final String BYTES_READ_RATE = "bytesreadrate";
public static final String BYTES_WRITE_RATE = "byteswriterate";
+ public static final String BYPASS_VLAN_OVERLAP_CHECK = "bypassvlanoverlapcheck";
public static final String CATEGORY = "category";
public static final String CAN_REVERT = "canrevert";
+ public static final String CA_CERTIFICATES = "cacertificates";
public static final String CERTIFICATE = "certificate";
public static final String CERTIFICATE_CHAIN = "certchain";
public static final String CERTIFICATE_FINGERPRINT = "fingerprint";
public static final String CERTIFICATE_ID = "certid";
+ public static final String CSR = "csr";
public static final String PRIVATE_KEY = "privatekey";
public static final String DOMAIN_SUFFIX = "domainsuffix";
public static final String DNS_SEARCH_ORDER = "dnssearchorder";
@@ -54,6 +60,7 @@
public static final String CLUSTER_ID = "clusterid";
public static final String CLUSTER_NAME = "clustername";
public static final String CLUSTER_TYPE = "clustertype";
+ public static final String CN = "cn";
public static final String COMMAND = "command";
public static final String CMD_EVENT_TYPE = "cmdeventtype";
public static final String COMPONENT = "component";
@@ -95,6 +102,7 @@
public static final String DOMAIN_ID = "domainid";
public static final String DOMAIN__ID = "domainId";
public static final String DURATION = "duration";
+ public static final String ELIGIBLE = "eligible";
public static final String EMAIL = "email";
public static final String END_DATE = "enddate";
public static final String END_IP = "endip";
@@ -102,6 +110,7 @@
public static final String END_PORT = "endport";
public static final String ENTRY_TIME = "entrytime";
public static final String EXPIRES = "expires";
+ public static final String FENCE = "fence";
public static final String FETCH_LATEST = "fetchlatest";
public static final String FIRSTNAME = "firstname";
public static final String FORCED = "forced";
@@ -120,6 +129,9 @@
public static final String GUEST_CIDR_ADDRESS = "guestcidraddress";
public static final String GUEST_VLAN_RANGE = "guestvlanrange";
public static final String HA_ENABLE = "haenable";
+ public static final String HA_PROVIDER = "haprovider";
+ public static final String HA_STATE = "hastate";
+ public static final String HEALTH = "health";
public static final String HOST_ID = "hostid";
public static final String HOST_NAME = "hostname";
public static final String HYPERVISOR = "hypervisor";
@@ -163,6 +175,7 @@
public static final String LUN = "lun";
public static final String LBID = "lbruleid";
public static final String MAX = "max";
+ public static final String MAC_ADDRESS = "macaddress";
public static final String MAX_SNAPS = "maxsnaps";
public static final String MEMORY = "memory";
public static final String MODE = "mode";
@@ -216,6 +229,8 @@
public static final String PUBLIC_END_PORT = "publicendport";
public static final String PUBLIC_ZONE = "publiczone";
public static final String RECEIVED_BYTES = "receivedbytes";
+ public static final String RECONNECT = "reconnect";
+ public static final String RECOVER = "recover";
public static final String REQUIRES_HVM = "requireshvm";
public static final String RESOURCE_TYPE = "resourcetype";
public static final String RESPONSE = "response";
@@ -234,6 +249,7 @@
public static final String SECURITY_GROUP_ID = "securitygroupid";
public static final String SENT = "sent";
public static final String SENT_BYTES = "sentbytes";
+ public static final String SERIAL = "serial";
public static final String SERVICE_OFFERING_ID = "serviceofferingid";
public static final String SESSIONKEY = "sessionkey";
public static final String SHOW_CAPACITIES = "showcapacities";
@@ -373,6 +389,7 @@
public static final String ROLE_NAME = "rolename";
public static final String PERMISSION = "permission";
public static final String RULE = "rule";
+ public static final String RULE_ID = "ruleid";
public static final String RULE_ORDER = "ruleorder";
public static final String USER = "user";
public static final String ACTIVE_ONLY = "activeonly";
@@ -652,10 +669,22 @@
public static final String OVM3_CLUSTER = "ovm3cluster";
public static final String OVM3_VIP = "ovm3vip";
public static final String CLEAN_UP_DETAILS = "cleanupdetails";
+ public static final String VIRTUAL_SIZE = "virtualsize";
+ public static final String NETSCALER_CONTROLCENTER_ID = "netscalercontrolcenterid";
+ public static final String NETSCALER_SERVICEPACKAGE_ID = "netscalerservicepackageid";
public static final String ZONE_ID_LIST = "zoneids";
public static final String DESTINATION_ZONE_ID_LIST = "destzoneids";
public static final String ADMIN = "admin";
+ public static final String CHECKSUM_PARAMETER_PREFIX_DESCRIPTION = "The parameter containing the checksum will be considered a MD5sum if it is not prefixed\n"
+ + " and just a plain ascii/utf8 representation of a hexadecimal string. If it is required to\n"
+ + " use another algorithm the hexadecimal string is to be prefixed with a string of the form,\n"
+ + " \"{<algorithm>}\", not including the double quotes. In this <algorithm> is the exact string\n"
+ + " representing the java supported algorithm, i.e. MD5 or SHA-256. Note that java does not\n"
+ + " contain an algorithm called SHA256 or one called sha-256, only SHA-256.";
+
+ public static final String HAS_ANNOTATION = "hasannotation";
+ public static final String LAST_ANNOTATED = "lastannotated";
public enum HostDetails {
all, capacity, events, stats, min;
@@ -664,4 +693,8 @@
public enum VMDetails {
all, group, nics, stats, secgrp, tmpl, servoff, diskoff, iso, volume, min, affgrp;
}
+
+ public enum DomainDetails {
+ all, resource, min;
+ }
}
diff --git a/api/src/org/apache/cloudstack/api/BaseCmd.java b/api/src/org/apache/cloudstack/api/BaseCmd.java
index 5be75196d39..37dbeaab841 100644
--- a/api/src/org/apache/cloudstack/api/BaseCmd.java
+++ b/api/src/org/apache/cloudstack/api/BaseCmd.java
@@ -17,32 +17,6 @@
package org.apache.cloudstack.api;
-import java.lang.reflect.Field;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Pattern;
-
-import javax.inject.Inject;
-
-import com.cloud.utils.HttpUtils;
-import org.apache.cloudstack.acl.RoleService;
-import org.apache.log4j.Logger;
-
-import org.apache.cloudstack.acl.RoleType;
-import org.apache.cloudstack.affinity.AffinityGroupService;
-import org.apache.cloudstack.alert.AlertService;
-import org.apache.cloudstack.context.CallContext;
-import org.apache.cloudstack.network.element.InternalLoadBalancerElementService;
-import org.apache.cloudstack.network.lb.ApplicationLoadBalancerService;
-import org.apache.cloudstack.network.lb.InternalLoadBalancerVMService;
-import org.apache.cloudstack.query.QueryService;
-import org.apache.cloudstack.usage.UsageService;
-
import com.cloud.configuration.ConfigurationService;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
@@ -78,11 +52,35 @@
import com.cloud.user.AccountService;
import com.cloud.user.DomainService;
import com.cloud.user.ResourceLimitService;
+import com.cloud.utils.HttpUtils;
import com.cloud.utils.ReflectUtil;
import com.cloud.utils.db.EntityManager;
import com.cloud.utils.db.UUIDManager;
import com.cloud.vm.UserVmService;
import com.cloud.vm.snapshot.VMSnapshotService;
+import org.apache.cloudstack.acl.RoleService;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.affinity.AffinityGroupService;
+import org.apache.cloudstack.alert.AlertService;
+import org.apache.cloudstack.annotation.AnnotationService;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.network.element.InternalLoadBalancerElementService;
+import org.apache.cloudstack.network.lb.ApplicationLoadBalancerService;
+import org.apache.cloudstack.network.lb.InternalLoadBalancerVMService;
+import org.apache.cloudstack.query.QueryService;
+import org.apache.cloudstack.usage.UsageService;
+import org.apache.log4j.Logger;
+
+import javax.inject.Inject;
+import java.lang.reflect.Field;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
public abstract class BaseCmd {
private static final Logger s_logger = Logger.getLogger(BaseCmd.class.getName());
@@ -93,6 +91,7 @@
public static Pattern newInputDateFormat = Pattern.compile("[\\d]+-[\\d]+-[\\d]+ [\\d]+:[\\d]+:[\\d]+");
private static final DateFormat s_outputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
protected static final Map<Class<?>, List<Field>> fieldsForCmdClass = new HashMap<Class<?>, List<Field>>();
+
public static enum HTTPMethod {
GET, POST, PUT, DELETE
}
@@ -192,6 +191,8 @@
public AlertService _alertSvc;
@Inject
public UUIDManager _uuidMgr;
+ @Inject
+ public AnnotationService annotationService;
public abstract void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
ResourceAllocationException, NetworkRuleConflictException;
diff --git a/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java b/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java
index 2e1fbd6f861..074df8d5fc2 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java
@@ -184,7 +184,7 @@ public long getEntityOwnerId() {
@Override
public void execute() {
validateParams();
- CallContext.current().setEventDetails("Account Name: " + getAccountName() + ", Domain Id:" + getDomainId());
+ CallContext.current().setEventDetails("Account Name: " + getUsername() + ", Domain Id:" + getDomainId());
UserAccount userAccount =
_accountService.createUserAccount(getUsername(), getPassword(), getFirstName(), getLastName(), getEmail(), getTimeZone(), getAccountName(), getAccountType(), getRoleId(),
getDomainId(), getNetworkDomain(), getDetails(), getAccountUUID(), getUserUUID());
diff --git a/api/src/org/apache/cloudstack/api/command/admin/acl/UpdateRolePermissionCmd.java b/api/src/org/apache/cloudstack/api/command/admin/acl/UpdateRolePermissionCmd.java
index 055265c5ccc..045464eab79 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/acl/UpdateRolePermissionCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/acl/UpdateRolePermissionCmd.java
@@ -20,6 +20,7 @@
import com.cloud.user.Account;
import org.apache.cloudstack.acl.Role;
import org.apache.cloudstack.acl.RolePermission;
+import org.apache.cloudstack.acl.RolePermission.Permission;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiArgValidator;
@@ -51,10 +52,18 @@
description = "ID of the role", validations = {ApiArgValidator.PositiveNumber})
private Long roleId;
- @Parameter(name = ApiConstants.RULE_ORDER, type = CommandType.LIST, collectionType = CommandType.UUID, required = true, entityType = RolePermissionResponse.class,
+ @Parameter(name = ApiConstants.RULE_ORDER, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = RolePermissionResponse.class,
description = "The parent role permission uuid, use 0 to move this rule at the top of the list")
private List<Long> rulePermissionOrder;
+ @Parameter(name = ApiConstants.RULE_ID, type = CommandType.UUID, entityType = RolePermissionResponse.class,
+ description = "Role permission rule id", since="4.11")
+ private Long ruleId;
+
+ @Parameter(name = ApiConstants.PERMISSION, type = CommandType.STRING,
+ description = "Rule permission, can be: allow or deny", since="4.11")
+ private String rulePermission;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -67,6 +76,21 @@ public Long getRoleId() {
return rulePermissionOrder;
}
+ public Long getRuleId() {
+ return ruleId;
+ }
+
+ public Permission getRulePermission() {
+ if (this.rulePermission == null) {
+ return null;
+ }
+ if (!this.rulePermission.equalsIgnoreCase(Permission.ALLOW.toString()) &&
+ !this.rulePermission.equalsIgnoreCase(Permission.DENY.toString())) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Values for permission parameter should be: allow or deny");
+ }
+ return rulePermission.equalsIgnoreCase(Permission.ALLOW.toString()) ? Permission.ALLOW : Permission.DENY;
+ }
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@@ -84,19 +108,35 @@ public long getEntityOwnerId() {
@Override
public void execute() {
final Role role = roleService.findRole(getRoleId());
+ boolean result = false;
if (role == null) {
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Invalid role id provided");
}
- CallContext.current().setEventDetails("Reordering permissions for role id: " + role.getId());
- final List<RolePermission> rolePermissionsOrder = new ArrayList<>();
- for (Long rolePermissionId : getRulePermissionOrder()) {
- final RolePermission rolePermission = roleService.findRolePermission(rolePermissionId);
+ if (getRulePermissionOrder() != null) {
+ if (getRuleId() != null || getRulePermission() != null) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Parameters permission and ruleid must be mutually exclusive with ruleorder");
+ }
+ CallContext.current().setEventDetails("Reordering permissions for role id: " + role.getId());
+ final List<RolePermission> rolePermissionsOrder = new ArrayList<>();
+ for (Long rolePermissionId : getRulePermissionOrder()) {
+ final RolePermission rolePermission = roleService.findRolePermission(rolePermissionId);
+ if (rolePermission == null) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Provided role permission(s) do not exist");
+ }
+ rolePermissionsOrder.add(rolePermission);
+ }
+ result = roleService.updateRolePermission(role, rolePermissionsOrder);
+ } else if (getRuleId() != null && getRulePermission() != null) {
+ if (getRulePermissionOrder() != null) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Parameters permission and ruleid must be mutually exclusive with ruleorder");
+ }
+ RolePermission rolePermission = roleService.findRolePermission(getRuleId());
if (rolePermission == null) {
- throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Provided role permission(s) do not exist");
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Invalid rule id provided");
}
- rolePermissionsOrder.add(rolePermission);
+ CallContext.current().setEventDetails("Updating permission for rule id: " + getRuleId() + " to: " + getRulePermission().toString());
+ result = roleService.updateRolePermission(role, rolePermission, getRulePermission());
}
- boolean result = roleService.updateRolePermission(role, rolePermissionsOrder);
SuccessResponse response = new SuccessResponse(getCommandName());
response.setSuccess(result);
setResponseObject(response);
diff --git a/api/src/org/apache/cloudstack/api/command/admin/address/AcquirePodIpCmdByAdmin.java b/api/src/org/apache/cloudstack/api/command/admin/address/AcquirePodIpCmdByAdmin.java
new file mode 100644
index 00000000000..fea0ca64d9c
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/address/AcquirePodIpCmdByAdmin.java
@@ -0,0 +1,92 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.command.admin.address;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.AcquirePodIpCmdResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+
+@APICommand(name = "acquirePodIpAddress", description = "Allocates IP addresses in respective Pod of a Zone", responseObject = AcquirePodIpCmdResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+public class AcquirePodIpCmdByAdmin extends BaseCmd {
+
+ public static final Logger s_logger = Logger.getLogger(AcquirePodIpCmdByAdmin.class.getName());
+ private static final String s_name = "acquirepodipaddress";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.ZONE_ID, type = CommandType.STRING, entityType = ZoneResponse.class, required = true, description = "the ID of the zone")
+ private String zoneId;
+
+ @Parameter(name = ApiConstants.POD_ID, type = CommandType.STRING, entityType = ZoneResponse.class, required = false, description = "Pod ID")
+ private String podId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ private String getZoneId() {
+ return zoneId;
+ }
+
+ public String getPodId() {
+ return podId;
+ }
+
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException, ResourceAllocationException, ConcurrentOperationException {
+ AcquirePodIpCmdResponse podIp = null;
+ podIp = _networkService.allocatePodIp(_accountService.getAccount(getEntityOwnerId()), getZoneId(), getPodId());
+ if (podIp != null) {
+ podIp.setResponseName(getCommandName());
+ podIp.setObjectName(getCommandName());
+ setResponseObject(podIp);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to assign IP address");
+ }
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccount().getAccountId();
+ }
+
+}
\ No newline at end of file
diff --git a/api/src/org/apache/cloudstack/api/command/admin/address/ReleasePodIpCmdByAdmin.java b/api/src/org/apache/cloudstack/api/command/admin/address/ReleasePodIpCmdByAdmin.java
new file mode 100644
index 00000000000..750a85d57f2
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/address/ReleasePodIpCmdByAdmin.java
@@ -0,0 +1,79 @@
+//Licensed to the Apache Software Foundation (ASF) under one
+//or more contributor license agreements. See the NOTICE file
+//distributed with this work for additional information
+//regarding copyright ownership. The ASF licenses this file
+//to you under the Apache License, Version 2.0 (the
+//"License"); you may not use this file except in compliance
+//with the License. You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing,
+//software distributed under the License is distributed on an
+//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+//KIND, either express or implied. See the License for the
+//specific language governing permissions and limitations
+//under the License.
+package org.apache.cloudstack.api.command.admin.address;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.command.admin.vlan.ReleasePublicIpRangeCmd;
+import org.apache.cloudstack.api.response.AcquireIPAddressResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+
+import com.cloud.user.Account;
+
+@APICommand(name = "releasePodIpAddress", description = "Releases a Pod IP back to the Pod", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+public class ReleasePodIpCmdByAdmin extends BaseCmd {
+ public static final Logger s_logger = Logger.getLogger(ReleasePublicIpRangeCmd.class.getName());
+
+ private static final String s_name = "releasepodipresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.ID, type = CommandType.LONG, entityType = AcquireIPAddressResponse.class, required = true, description = "UUID of the Pod IP")
+ private Long id;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public long getId() {
+ return id;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute() {
+ boolean result = _networkService.releasePodIp(this);
+ if (result) {
+ SuccessResponse response = new SuccessResponse(getCommandName());
+ response.setDisplayText("IP is released sucessfully");
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to release Pod ip ");
+ }
+ }
+}
\ No newline at end of file
diff --git a/api/src/org/apache/cloudstack/api/command/admin/annotation/AddAnnotationCmd.java b/api/src/org/apache/cloudstack/api/command/admin/annotation/AddAnnotationCmd.java
new file mode 100644
index 00000000000..07a73ce095f
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/annotation/AddAnnotationCmd.java
@@ -0,0 +1,86 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.command.admin.annotation;
+
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.google.common.base.Preconditions;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.annotation.AnnotationService;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.AnnotationResponse;
+import org.apache.cloudstack.context.CallContext;
+
+@APICommand(name = AddAnnotationCmd.APINAME, description = "add an annotation.", responseObject = AnnotationResponse.class,
+ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.11", authorized = {RoleType.Admin})
+public class AddAnnotationCmd extends BaseCmd {
+
+ public static final String APINAME = "addAnnotation";
+
+ @Parameter(name = ApiConstants.ANNOTATION, type = CommandType.STRING, description = "the annotation text")
+ private String annotation;
+ @Parameter(name = ApiConstants.ENTITY_TYPE, type = CommandType.STRING, description = "the entity type (only HOST is allowed atm)")
+ private String entityType;
+ @Parameter(name = ApiConstants.ENTITY_ID, type = CommandType.STRING, description = "the id of the entity to annotate")
+ private String entityUuid;
+
+ public String getAnnotation() {
+ return annotation;
+ }
+
+ protected void setEntityType(String newType) {
+ entityType = newType;
+ }
+ public AnnotationService.EntityType getEntityType() {
+ return AnnotationService.EntityType.valueOf(entityType);
+ }
+
+ protected void setEntityUuid(String newUuid) {
+ entityUuid = newUuid;
+ }
+ public String getEntityUuid() {
+ return entityUuid;
+ }
+
+ @Override
+ public void execute()
+ throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException,
+ NetworkRuleConflictException {
+ Preconditions.checkNotNull(getEntityUuid(),"I have to have an entity to set an annotation on!");
+ Preconditions.checkState(AnnotationService.EntityType.contains(entityType),(java.lang.String)"'%s' is ot a valid EntityType to put annotations on", entityType);
+ AnnotationResponse annotationResponse = annotationService.addAnnotation(this);
+ annotationResponse.setResponseName(getCommandName());
+ this.setResponseObject(annotationResponse);
+ }
+
+ @Override
+ public String getCommandName() {
+ return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccount().getAccountId();
+ }
+}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/annotation/ListAnnotationsCmd.java b/api/src/org/apache/cloudstack/api/command/admin/annotation/ListAnnotationsCmd.java
new file mode 100644
index 00000000000..4657eb9e16a
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/annotation/ListAnnotationsCmd.java
@@ -0,0 +1,81 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.command.admin.annotation;
+
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.utils.StringUtils;
+import com.google.common.base.Preconditions;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.AnnotationResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+
+@APICommand(name = ListAnnotationsCmd.APINAME, description = "Lists annotations.", responseObject = AnnotationResponse.class,
+ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.11", authorized = {RoleType.Admin})
+public class ListAnnotationsCmd extends BaseListCmd {
+
+ public static final String APINAME = "listAnnotations";
+
+ @Parameter(name = ApiConstants.ID, type = CommandType.STRING, description = "the id of the annotation")
+ private String uuid;
+ @Parameter(name = ApiConstants.ENTITY_TYPE, type = CommandType.STRING, description = "the entity type")
+ private String entityType;
+ @Parameter(name = ApiConstants.ENTITY_ID, type = CommandType.STRING, description = "the id of the entity for which to show annotations")
+ private String entityUuid;
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public String getEntityType() {
+ return entityType;
+ }
+
+ public String getEntityUuid() {
+ return entityUuid;
+ }
+
+ @Override public void execute()
+ throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException,
+ NetworkRuleConflictException {
+ // preconditions to check:
+ // if entity type is null entity uuid can not have a value
+ Preconditions.checkArgument(StringUtils.isNotBlank(entityType) ? ! StringUtils.isNotBlank(uuid) : true,
+ "I can search for an anotation on an entity or for a specific annotation, not both");
+ // if uuid has a value entity type and entity uuid can not have a value
+ Preconditions.checkArgument(StringUtils.isNotBlank(uuid) ? entityType == null && entityUuid == null : true,
+ "I will either search for a specific annotation or for annotations on an entity, not both");
+
+ ListResponse<AnnotationResponse> response = annotationService.searchForAnnotations(this);
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ response.setObjectName("annotations");
+ }
+
+ @Override public String getCommandName() {
+ return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
+ }
+}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/annotation/RemoveAnnotationCmd.java b/api/src/org/apache/cloudstack/api/command/admin/annotation/RemoveAnnotationCmd.java
new file mode 100644
index 00000000000..581ce45f252
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/annotation/RemoveAnnotationCmd.java
@@ -0,0 +1,64 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.command.admin.annotation;
+
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.AnnotationResponse;
+import org.apache.cloudstack.context.CallContext;
+
+@APICommand(name = RemoveAnnotationCmd.APINAME, description = "remove an annotation.", responseObject = AnnotationResponse.class,
+ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.11", authorized = {RoleType.Admin})
+public class RemoveAnnotationCmd extends BaseCmd {
+
+ public static final String APINAME = "removeAnnotation";
+
+ @Parameter(name = ApiConstants.ID, type = CommandType.STRING, required = true, description = "the id of the annotation")
+ private String uuid;
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ @Override
+ public void execute()
+ throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException,
+ NetworkRuleConflictException {
+ AnnotationResponse annotationResponse = annotationService.removeAnnotation(this);
+ annotationResponse.setResponseName(getCommandName());
+ this.setResponseObject(annotationResponse);
+ }
+
+ @Override
+ public String getCommandName() {
+ return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccount().getAccountId();
+ }
+}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/ca/IssueCertificateCmd.java b/api/src/org/apache/cloudstack/api/command/admin/ca/IssueCertificateCmd.java
new file mode 100644
index 00000000000..8926829205f
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/ca/IssueCertificateCmd.java
@@ -0,0 +1,162 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.api.command.admin.ca;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.CertificateResponse;
+import org.apache.cloudstack.ca.CAManager;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.framework.ca.Certificate;
+import org.apache.cloudstack.utils.security.CertUtils;
+import org.apache.log4j.Logger;
+
+import com.cloud.event.EventTypes;
+import com.google.common.base.Strings;
+
+@APICommand(name = IssueCertificateCmd.APINAME,
+ description = "Issues a client certificate using configured or provided CA plugin",
+ responseObject = CertificateResponse.class,
+ requestHasSensitiveInfo = true,
+ responseHasSensitiveInfo = true,
+ since = "4.11.0",
+ authorized = {RoleType.Admin})
+public class IssueCertificateCmd extends BaseAsyncCmd {
+ private static final Logger LOG = Logger.getLogger(IssueCertificateCmd.class);
+
+ public static final String APINAME = "issueCertificate";
+
+ @Inject
+ private CAManager caManager;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.CSR, type = BaseCmd.CommandType.STRING, description = "The certificate signing request (in pem format), if CSR is not provided then configured/provided options are considered", length = 65535)
+ private String csr;
+
+ @Parameter(name = ApiConstants.DOMAIN, type = BaseCmd.CommandType.STRING, description = "Comma separated list of domains, the certificate should be issued for. When csr is not provided, the first domain is used as a subject/CN")
+ private String domains;
+
+ @Parameter(name = ApiConstants.IP_ADDRESS, type = BaseCmd.CommandType.STRING, description = "Comma separated list of IP addresses, the certificate should be issued for")
+ private String addresses;
+
+ @Parameter(name = ApiConstants.DURATION, type = CommandType.INTEGER, description = "Certificate validity duration in number of days, when not provided the default configured value will be used")
+ private Integer validityDuration;
+
+ @Parameter(name = ApiConstants.PROVIDER, type = BaseCmd.CommandType.STRING, description = "Name of the CA service provider, otherwise the default configured provider plugin will be used")
+ private String provider;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public String getCsr() {
+ return csr;
+ }
+
+ private List<String> processList(final String string) {
+ final List<String> list = new ArrayList<>();
+ if (!Strings.isNullOrEmpty(string)) {
+ for (final String address: string.split(",")) {
+ list.add(address.trim());
+ }
+ }
+ return list;
+ }
+
+ public List<String> getAddresses() {
+ return processList(addresses);
+ }
+
+ public List<String> getDomains() {
+ return processList(domains);
+ }
+
+ public Integer getValidityDuration() {
+ return validityDuration;
+ }
+
+ public String getProvider() {
+ return provider;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public void execute() {
+ if (Strings.isNullOrEmpty(getCsr()) && getDomains().isEmpty()) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Please provide the domains or the CSR, none of them are provided");
+ }
+ final Certificate certificate = caManager.issueCertificate(getCsr(), getDomains(), getAddresses(), getValidityDuration(), getProvider());
+ if (certificate == null) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to issue client certificate with given provider");
+ }
+
+ final CertificateResponse certificateResponse = new CertificateResponse();
+ try {
+ certificateResponse.setCertificate(CertUtils.x509CertificateToPem(certificate.getClientCertificate()));
+ if (certificate.getPrivateKey() != null) {
+ certificateResponse.setPrivateKey(CertUtils.privateKeyToPem(certificate.getPrivateKey()));
+ }
+ if (certificate.getCaCertificates() != null) {
+ certificateResponse.setCaCertificate(CertUtils.x509CertificatesToPem(certificate.getCaCertificates()));
+ }
+ } catch (final IOException e) {
+ LOG.error("Failed to generate and convert client certificate(s) to PEM due to error: ", e);
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to process and return client certificate");
+ }
+ certificateResponse.setResponseName(getCommandName());
+ setResponseObject(certificateResponse);
+ }
+
+ @Override
+ public String getCommandName() {
+ return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccount().getId();
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_CA_CERTIFICATE_ISSUE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "issuing certificate for domain(s)=" + domains + ", ip(s)=" + addresses;
+ }
+}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/ca/ListCAProvidersCmd.java b/api/src/org/apache/cloudstack/api/command/admin/ca/ListCAProvidersCmd.java
new file mode 100644
index 00000000000..e1e8e375163
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/ca/ListCAProvidersCmd.java
@@ -0,0 +1,102 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.api.command.admin.ca;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.CAProviderResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.ca.CAManager;
+import org.apache.cloudstack.framework.ca.CAProvider;
+
+import com.cloud.user.Account;
+
+@APICommand(name = ListCAProvidersCmd.APINAME,
+ description = "Lists available certificate authority providers in CloudStack",
+ responseObject = CAProviderResponse.class,
+ requestHasSensitiveInfo = false,
+ responseHasSensitiveInfo = false,
+ since = "4.11.0",
+ authorized = {RoleType.Admin})
+public class ListCAProvidersCmd extends BaseCmd {
+ public static final String APINAME = "listCAProviders";
+
+ @Inject
+ private CAManager caManager;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "List CA service provider by name")
+ private String name;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public String getName() {
+ return name;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ private void setupResponse(final List<CAProvider> providers) {
+ final ListResponse<CAProviderResponse> response = new ListResponse<>();
+ final List<CAProviderResponse> responses = new ArrayList<>();
+ for (final CAProvider provider : providers) {
+ if (provider == null || (getName() != null && !provider.getProviderName().equals(getName()))) {
+ continue;
+ }
+ final CAProviderResponse caProviderResponse = new CAProviderResponse();
+ caProviderResponse.setName(provider.getProviderName());
+ caProviderResponse.setDescription(provider.getDescription());
+ caProviderResponse.setObjectName("caprovider");
+ responses.add(caProviderResponse);
+ }
+ response.setResponses(responses);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ }
+
+ @Override
+ public void execute() {
+ final List<CAProvider> caProviders = caManager.getCaProviders();
+ setupResponse(caProviders);
+ }
+}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/ca/ListCaCertificateCmd.java b/api/src/org/apache/cloudstack/api/command/admin/ca/ListCaCertificateCmd.java
new file mode 100644
index 00000000000..1baa84179f0
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/ca/ListCaCertificateCmd.java
@@ -0,0 +1,90 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.api.command.admin.ca;
+
+import java.io.IOException;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.CertificateResponse;
+import org.apache.cloudstack.ca.CAManager;
+
+import com.cloud.user.Account;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+@APICommand(name = ListCaCertificateCmd.APINAME,
+ description = "Lists the CA public certificate(s) as support by the configured/provided CA plugin",
+ responseObject = CertificateResponse.class,
+ requestHasSensitiveInfo = false,
+ responseHasSensitiveInfo = false,
+ since = "4.11.0",
+ authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
+public class ListCaCertificateCmd extends BaseCmd {
+ public static final String APINAME = "listCaCertificate";
+
+ @Inject
+ private CAManager caManager;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.PROVIDER, type = CommandType.STRING, description = "Name of the CA service provider, otherwise the default configured provider plugin will be used")
+ private String provider;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public String getProvider() {
+ return provider;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public void execute() {
+ final String caCertificates;
+ try {
+ caCertificates = caManager.getCaCertificate(getProvider());
+ } catch (final IOException e) {
+ throw new CloudRuntimeException("Failed to get CA certificates for given CA provider");
+ }
+ final CertificateResponse certificateResponse = new CertificateResponse("cacertificates");
+ certificateResponse.setCertificate(caCertificates);
+ certificateResponse.setResponseName(getCommandName());
+ setResponseObject(certificateResponse);
+ }
+
+ @Override
+ public String getCommandName() {
+ return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_TYPE_NORMAL;
+ }
+}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/ca/ProvisionCertificateCmd.java b/api/src/org/apache/cloudstack/api/command/admin/ca/ProvisionCertificateCmd.java
new file mode 100644
index 00000000000..2745f071dd0
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/ca/ProvisionCertificateCmd.java
@@ -0,0 +1,125 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.api.command.admin.ca;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.HostResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.ca.CAManager;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.event.EventTypes;
+import com.cloud.host.Host;
+
+@APICommand(name = ProvisionCertificateCmd.APINAME,
+ description = "Issues and propagates client certificate on a connected host/agent using configured CA plugin",
+ responseObject = SuccessResponse.class,
+ requestHasSensitiveInfo = false,
+ responseHasSensitiveInfo = false,
+ since = "4.11.0",
+ authorized = {RoleType.Admin})
+public class ProvisionCertificateCmd extends BaseAsyncCmd {
+ public static final String APINAME = "provisionCertificate";
+
+ @Inject
+ private CAManager caManager;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.HOST_ID, type = CommandType.UUID, required = true, entityType = HostResponse.class,
+ description = "The host/agent uuid to which the certificate has to be provisioned (issued and propagated)")
+ private Long hostId;
+
+ @Parameter(name = ApiConstants.RECONNECT, type = CommandType.BOOLEAN,
+ description = "Whether to attempt reconnection with host/agent after successful deployment of certificate. When option is not provided, configured global setting is used")
+ private Boolean reconnect;
+
+ @Parameter(name = ApiConstants.PROVIDER, type = CommandType.STRING,
+ description = "Name of the CA service provider, otherwise the default configured provider plugin will be used")
+ private String provider;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getHostId() {
+ return hostId;
+ }
+
+ public Boolean getReconnect() {
+ return reconnect;
+ }
+
+ public String getProvider() {
+ return provider;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public void execute() {
+ final Host host = _resourceService.getHost(getHostId());
+ if (host == null) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to find host by ID: " + getHostId());
+ }
+
+ boolean result = caManager.provisionCertificate(host, getReconnect(), getProvider());
+ SuccessResponse response = new SuccessResponse(getCommandName());
+ response.setSuccess(result);
+ setResponseObject(response);
+ }
+
+ @Override
+ public String getCommandName() {
+ return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccount().getId();
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_CA_CERTIFICATE_PROVISION;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "provisioning certificate for host id=" + hostId + " using provider=" + provider;
+ }
+
+ @Override
+ public ApiCommandJobType getInstanceType() {
+ return ApiCommandJobType.Host;
+ }
+}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/ca/RevokeCertificateCmd.java b/api/src/org/apache/cloudstack/api/command/admin/ca/RevokeCertificateCmd.java
new file mode 100644
index 00000000000..0f154f045df
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/ca/RevokeCertificateCmd.java
@@ -0,0 +1,116 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.api.command.admin.ca;
+
+import java.math.BigInteger;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.ca.CAManager;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.event.EventTypes;
+import com.google.common.base.Strings;
+
+@APICommand(name = RevokeCertificateCmd.APINAME,
+ description = "Revokes certificate using configured CA plugin",
+ responseObject = SuccessResponse.class,
+ requestHasSensitiveInfo = true,
+ responseHasSensitiveInfo = false,
+ since = "4.11.0",
+ authorized = {RoleType.Admin})
+public class RevokeCertificateCmd extends BaseAsyncCmd {
+
+ public static final String APINAME = "revokeCertificate";
+
+ @Inject
+ private CAManager caManager;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.SERIAL, type = BaseCmd.CommandType.STRING, required = true, description = "The certificate serial number, as a hex value")
+ private String serial;
+
+ @Parameter(name = ApiConstants.CN, type = BaseCmd.CommandType.STRING, description = "The certificate CN")
+ private String cn;
+
+ @Parameter(name = ApiConstants.PROVIDER, type = BaseCmd.CommandType.STRING, description = "Name of the CA service provider, otherwise the default configured provider plugin will be used")
+ private String provider;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public BigInteger getSerialBigInteger() {
+ if (Strings.isNullOrEmpty(serial)) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Certificate serial cannot be empty");
+ }
+ return new BigInteger(serial, 16);
+ }
+
+ public String getCn() {
+ return cn;
+ }
+
+ public String getProvider() {
+ return provider;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public void execute() {
+ boolean result = caManager.revokeCertificate(getSerialBigInteger(), getCn(), getProvider());
+ SuccessResponse response = new SuccessResponse(getCommandName());
+ response.setSuccess(result);
+ setResponseObject(response);
+ }
+
+ @Override
+ public String getCommandName() {
+ return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccount().getId();
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_CA_CERTIFICATE_REVOKE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "revoking certificate with serial id=" + serial + ", cn=" + cn;
+ }
+}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/domain/CreateDomainCmd.java b/api/src/org/apache/cloudstack/api/command/admin/domain/CreateDomainCmd.java
index 312c9ee4b09..fe1c20206b6 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/domain/CreateDomainCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/domain/CreateDomainCmd.java
@@ -17,7 +17,7 @@
package org.apache.cloudstack.api.command.admin.domain;
import org.apache.log4j.Logger;
-
+import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
@@ -31,7 +31,8 @@
import com.cloud.user.Account;
@APICommand(name = "createDomain", description = "Creates a domain", responseObject = DomainResponse.class,
- requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = {
+ RoleType.Admin, RoleType.DomainAdmin })
public class CreateDomainCmd extends BaseCmd {
public static final Logger s_logger = Logger.getLogger(CreateDomainCmd.class.getName());
@@ -45,9 +46,9 @@
private String domainName;
@Parameter(name = ApiConstants.PARENT_DOMAIN_ID,
- type = CommandType.UUID,
- entityType = DomainResponse.class,
- description = "assigns new domain a parent domain by domain ID of the parent. If no parent domain is specied, the ROOT domain is assumed.")
+ type = CommandType.UUID,
+ entityType = DomainResponse.class,
+ description = "assigns new domain a parent domain by domain ID of the parent. If no parent domain is specied, the ROOT domain is assumed.")
private Long parentDomainId;
@Parameter(name = ApiConstants.NETWORK_DOMAIN, type = CommandType.STRING, description = "Network domain for networks in the domain")
diff --git a/api/src/org/apache/cloudstack/api/command/admin/domain/DeleteDomainCmd.java b/api/src/org/apache/cloudstack/api/command/admin/domain/DeleteDomainCmd.java
index a6d2b0b10c1..037cf3d9ab4 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/domain/DeleteDomainCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/domain/DeleteDomainCmd.java
@@ -18,8 +18,7 @@
import javax.inject.Inject;
-import org.apache.log4j.Logger;
-
+import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
@@ -30,13 +29,15 @@
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.region.RegionService;
+import org.apache.log4j.Logger;
import com.cloud.domain.Domain;
import com.cloud.event.EventTypes;
import com.cloud.user.Account;
@APICommand(name = "deleteDomain", description = "Deletes a specified domain", responseObject = SuccessResponse.class,
- requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = {
+ RoleType.Admin, RoleType.DomainAdmin })
public class DeleteDomainCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(DeleteDomainCmd.class.getName());
private static final String s_name = "deletedomainresponse";
@@ -49,8 +50,8 @@
private Long id;
@Parameter(name = ApiConstants.CLEANUP,
- type = CommandType.BOOLEAN,
- description = "true if all domain resources (child domains, accounts) have to be cleaned up, false otherwise")
+ type = CommandType.BOOLEAN,
+ description = "true if all domain resources (child domains, accounts) have to be cleaned up, false otherwise")
private Boolean cleanup;
@Inject
diff --git a/api/src/org/apache/cloudstack/api/command/admin/domain/ListDomainsCmd.java b/api/src/org/apache/cloudstack/api/command/admin/domain/ListDomainsCmd.java
index e382ed9b41c..9c1ae221328 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/domain/ListDomainsCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/domain/ListDomainsCmd.java
@@ -16,10 +16,15 @@
// under the License.
package org.apache.cloudstack.api.command.admin.domain;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.List;
+
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiConstants.DomainDetails;
import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
@@ -27,6 +32,7 @@
import org.apache.cloudstack.api.response.ListResponse;
import com.cloud.domain.Domain;
+import com.cloud.exception.InvalidParameterValueException;
@APICommand(name = "listDomains", description = "Lists domains and provides detailed information for listed domains", responseObject = DomainResponse.class, responseView = ResponseView.Restricted, entityType = {Domain.class},
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
@@ -53,6 +59,12 @@
description = "If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false")
private Boolean listAll;
+ @Parameter(name = ApiConstants.DETAILS,
+ type = CommandType.LIST,
+ collectionType = CommandType.STRING,
+ description = "comma separated list of domain details requested, value can be a list of [ all, resource, min]")
+ private List<String> viewDetails;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -73,6 +85,25 @@ public boolean listAll() {
return listAll == null ? false : listAll;
}
+ public EnumSet<DomainDetails> getDetails() throws InvalidParameterValueException {
+ EnumSet<DomainDetails> dv;
+ if (viewDetails == null || viewDetails.size() <= 0) {
+ dv = EnumSet.of(DomainDetails.all);
+ } else {
+ try {
+ ArrayList<DomainDetails> dc = new ArrayList<DomainDetails>();
+ for (String detail : viewDetails) {
+ dc.add(DomainDetails.valueOf(detail));
+ }
+ dv = EnumSet.copyOf(dc);
+ } catch (IllegalArgumentException e) {
+ throw new InvalidParameterValueException("The details parameter contains a non permitted value. The allowed values are " +
+ EnumSet.allOf(DomainDetails.class));
+ }
+ }
+ return dv;
+ }
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
diff --git a/api/src/org/apache/cloudstack/api/command/admin/ha/ConfigureHAForHostCmd.java b/api/src/org/apache/cloudstack/api/command/admin/ha/ConfigureHAForHostCmd.java
new file mode 100644
index 00000000000..f85dbb23504
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/ha/ConfigureHAForHostCmd.java
@@ -0,0 +1,127 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.api.command.admin.ha;
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.host.Host;
+import com.cloud.user.Account;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiArgValidator;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.HostHAResponse;
+import org.apache.cloudstack.api.response.HostResponse;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.ha.HAConfigManager;
+import org.apache.cloudstack.ha.HAResource;
+
+import javax.inject.Inject;
+
+@APICommand(name = ConfigureHAForHostCmd.APINAME, description = "Configures HA for a host",
+ responseObject = HostHAResponse.class,
+ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
+ since = "4.11", authorized = {RoleType.Admin})
+public final class ConfigureHAForHostCmd extends BaseAsyncCmd {
+ public static final String APINAME = "configureHAForHost";
+
+ @Inject
+ private HAConfigManager haConfigManager;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.HOST_ID, type = CommandType.UUID, entityType = HostResponse.class,
+ description = "ID of the host", required = true, validations = {ApiArgValidator.PositiveNumber})
+ private Long hostId;
+
+ @Parameter(name = ApiConstants.PROVIDER, type = CommandType.STRING,
+ description = "HA provider", required = true, validations = {ApiArgValidator.NotNullOrEmpty})
+ private String haProvider;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getHostId() {
+ return hostId;
+ }
+
+ public String getHaProvider() {
+ return haProvider;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ private void setupResponse(final boolean result, final String resourceUuid) {
+ final HostHAResponse response = new HostHAResponse();
+ response.setId(resourceUuid);
+ response.setProvider(getHaProvider().toLowerCase());
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
+ final Host host = _resourceService.getHost(getHostId());
+ if (host == null) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to find host by ID: " + getHostId());
+ }
+
+ final boolean result = haConfigManager.configureHA(host.getId(), HAResource.ResourceType.Host, getHaProvider());
+ if (!result) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to configure HA provider for the host");
+ }
+ CallContext.current().setEventDetails("Host Id:" + host.getId() + " HA configured with provider: " + getHaProvider());
+ CallContext.current().putContextParameter(Host.class, host.getUuid());
+
+ setupResponse(result, host.getUuid());
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_HA_RESOURCE_DISABLE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "configure HA for host: " + getHostId();
+ }
+}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/ha/DisableHAForClusterCmd.java b/api/src/org/apache/cloudstack/api/command/admin/ha/DisableHAForClusterCmd.java
new file mode 100644
index 00000000000..053c978b831
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/ha/DisableHAForClusterCmd.java
@@ -0,0 +1,114 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.api.command.admin.ha;
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.org.Cluster;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiArgValidator;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.ClusterResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.ha.HAConfigManager;
+
+import javax.inject.Inject;
+
+@APICommand(name = DisableHAForClusterCmd.APINAME, description = "Disables HA cluster-wide",
+ responseObject = SuccessResponse.class,
+ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
+ since = "4.11", authorized = {RoleType.Admin})
+public final class DisableHAForClusterCmd extends BaseAsyncCmd {
+ public static final String APINAME = "disableHAForCluster";
+
+ @Inject
+ private HAConfigManager haConfigManager;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.CLUSTER_ID, type = BaseCmd.CommandType.UUID, entityType = ClusterResponse.class,
+ description = "ID of the cluster", required = true, validations = {ApiArgValidator.PositiveNumber})
+ private Long clusterId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getClusterId() {
+ return clusterId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccountId();
+ }
+
+ private void setupResponse(final boolean result) {
+ final SuccessResponse response = new SuccessResponse();
+ response.setSuccess(result);
+ response.setResponseName(getCommandName());
+ response.setObjectName("ha");
+ setResponseObject(response);
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
+ final Cluster cluster = _resourceService.getCluster(getClusterId());
+ if (cluster == null) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to find cluster by ID: " + getClusterId());
+ }
+ final boolean result = haConfigManager.disableHA(cluster);
+ CallContext.current().setEventDetails("Cluster Id:" + cluster.getId() + " HA enabled: false");
+ CallContext.current().putContextParameter(Cluster.class, cluster.getUuid());
+
+ setupResponse(result);
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_HA_RESOURCE_DISABLE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "disable HA for cluster: " + getClusterId();
+ }
+
+}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/ha/DisableHAForHostCmd.java b/api/src/org/apache/cloudstack/api/command/admin/ha/DisableHAForHostCmd.java
new file mode 100644
index 00000000000..87ebe878ceb
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/ha/DisableHAForHostCmd.java
@@ -0,0 +1,116 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.api.command.admin.ha;
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.host.Host;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiArgValidator;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.HostHAResponse;
+import org.apache.cloudstack.api.response.HostResponse;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.ha.HAConfigManager;
+import org.apache.cloudstack.ha.HAResource;
+
+import javax.inject.Inject;
+
+@APICommand(name = DisableHAForHostCmd.APINAME, description = "Disables HA for a host",
+ responseObject = HostHAResponse.class,
+ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
+ since = "4.11", authorized = {RoleType.Admin})
+public final class DisableHAForHostCmd extends BaseAsyncCmd {
+ public static final String APINAME = "disableHAForHost";
+
+ @Inject
+ private HAConfigManager haConfigManager;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.HOST_ID, type = CommandType.UUID, entityType = HostResponse.class,
+ description = "ID of the host", required = true, validations = {ApiArgValidator.PositiveNumber})
+ private Long hostId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getHostId() {
+ return hostId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccountId();
+ }
+
+ private void setupResponse(final boolean result, final String resourceUuid) {
+ final HostHAResponse response = new HostHAResponse();
+ response.setId(resourceUuid);
+ response.setEnabled(false);
+ response.setStatus(result);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
+ final Host host = _resourceService.getHost(getHostId());
+ if (host == null) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to find host by ID: " + getHostId());
+ }
+
+ final boolean result = haConfigManager.disableHA(host.getId(), HAResource.ResourceType.Host);
+ CallContext.current().setEventDetails("Host Id:" + host.getId() + " HA enabled: false");
+ CallContext.current().putContextParameter(Host.class, host.getUuid());
+
+ setupResponse(result, host.getUuid());
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_HA_RESOURCE_DISABLE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "disable HA for host: " + getHostId();
+ }
+}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/ha/DisableHAForZoneCmd.java b/api/src/org/apache/cloudstack/api/command/admin/ha/DisableHAForZoneCmd.java
new file mode 100644
index 00000000000..845c4a663b5
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/ha/DisableHAForZoneCmd.java
@@ -0,0 +1,115 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.api.command.admin.ha;
+
+import com.cloud.dc.DataCenter;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiArgValidator;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.ha.HAConfigManager;
+
+import javax.inject.Inject;
+
+@APICommand(name = DisableHAForZoneCmd.APINAME, description = "Disables HA for a zone",
+ responseObject = SuccessResponse.class,
+ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
+ since = "4.11", authorized = {RoleType.Admin})
+public final class DisableHAForZoneCmd extends BaseAsyncCmd {
+ public static final String APINAME = "disableHAForZone";
+
+ @Inject
+ private HAConfigManager haConfigManager;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.ZONE_ID, type = BaseCmd.CommandType.UUID, entityType = ZoneResponse.class,
+ description = "ID of the zone", required = true, validations = {ApiArgValidator.PositiveNumber})
+ private Long zoneId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getZoneId() {
+ return zoneId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccountId();
+ }
+
+ private void setupResponse(final boolean result) {
+ final SuccessResponse response = new SuccessResponse();
+ response.setSuccess(result);
+ response.setResponseName(getCommandName());
+ response.setObjectName("ha");
+ setResponseObject(response);
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
+ final DataCenter dataCenter = _resourceService.getZone(getZoneId());
+ if (dataCenter == null) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to find zone by ID: " + getZoneId());
+ }
+
+ final boolean result = haConfigManager.disableHA(dataCenter);
+ CallContext.current().setEventDetails("Zone Id:" + dataCenter.getId() + " HA enabled: false");
+ CallContext.current().putContextParameter(DataCenter.class, dataCenter.getUuid());
+
+ setupResponse(result);
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_HA_RESOURCE_DISABLE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "disable HA for zone: " + getZoneId();
+ }
+
+}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/ha/EnableHAForClusterCmd.java b/api/src/org/apache/cloudstack/api/command/admin/ha/EnableHAForClusterCmd.java
new file mode 100644
index 00000000000..e06d0d2c1b0
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/ha/EnableHAForClusterCmd.java
@@ -0,0 +1,114 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.api.command.admin.ha;
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.org.Cluster;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiArgValidator;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.ClusterResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.ha.HAConfigManager;
+
+import javax.inject.Inject;
+
+@APICommand(name = EnableHAForClusterCmd.APINAME, description = "Enables HA cluster-wide",
+ responseObject = SuccessResponse.class,
+ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
+ since = "4.11", authorized = {RoleType.Admin})
+public final class EnableHAForClusterCmd extends BaseAsyncCmd {
+ public static final String APINAME = "enableHAForCluster";
+
+ @Inject
+ private HAConfigManager haConfigManager;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.CLUSTER_ID, type = BaseCmd.CommandType.UUID, entityType = ClusterResponse.class,
+ description = "ID of the cluster", required = true, validations = {ApiArgValidator.PositiveNumber})
+ private Long clusterId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getClusterId() {
+ return clusterId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccountId();
+ }
+
+ private void setupResponse(final boolean result) {
+ final SuccessResponse response = new SuccessResponse();
+ response.setSuccess(result);
+ response.setResponseName(getCommandName());
+ response.setObjectName("ha");
+ setResponseObject(response);
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
+ final Cluster cluster = _resourceService.getCluster(getClusterId());
+ if (cluster == null) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to find cluster by ID: " + getClusterId());
+ }
+
+ final boolean result = haConfigManager.enableHA(cluster);
+ CallContext.current().setEventDetails("Cluster Id:" + cluster.getId() + " HA enabled: true");
+ CallContext.current().putContextParameter(Cluster.class, cluster.getUuid());
+
+ setupResponse(result);
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_HA_RESOURCE_ENABLE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "enable HA for cluster: " + getClusterId();
+ }
+}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/ha/EnableHAForHostCmd.java b/api/src/org/apache/cloudstack/api/command/admin/ha/EnableHAForHostCmd.java
new file mode 100644
index 00000000000..b23841ad56f
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/ha/EnableHAForHostCmd.java
@@ -0,0 +1,116 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.api.command.admin.ha;
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.host.Host;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiArgValidator;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.HostHAResponse;
+import org.apache.cloudstack.api.response.HostResponse;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.ha.HAConfigManager;
+import org.apache.cloudstack.ha.HAResource;
+
+import javax.inject.Inject;
+
+@APICommand(name = EnableHAForHostCmd.APINAME, description = "Enables HA for a host",
+ responseObject = HostHAResponse.class,
+ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
+ since = "4.11", authorized = {RoleType.Admin})
+public final class EnableHAForHostCmd extends BaseAsyncCmd {
+ public static final String APINAME = "enableHAForHost";
+
+ @Inject
+ private HAConfigManager haConfigManager;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.HOST_ID, type = CommandType.UUID, entityType = HostResponse.class,
+ description = "ID of the host", required = true, validations = {ApiArgValidator.PositiveNumber})
+ private Long hostId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getHostId() {
+ return hostId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccountId();
+ }
+
+ private void setupResponse(final boolean result, final String resourceUuid) {
+ final HostHAResponse response = new HostHAResponse();
+ response.setId(resourceUuid);
+ response.setEnabled(true);
+ response.setStatus(result);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
+ final Host host = _resourceService.getHost(getHostId());
+ if (host == null) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to find host by ID: " + getHostId());
+ }
+ final boolean result = haConfigManager.enableHA(host.getId(), HAResource.ResourceType.Host);
+
+ CallContext.current().setEventDetails("Host Id:" + host.getId() + " HA enabled: true");
+ CallContext.current().putContextParameter(Host.class, host.getUuid());
+
+ setupResponse(result, host.getUuid());
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_HA_RESOURCE_ENABLE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "enable HA for host: " + getHostId();
+ }
+}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/ha/EnableHAForZoneCmd.java b/api/src/org/apache/cloudstack/api/command/admin/ha/EnableHAForZoneCmd.java
new file mode 100644
index 00000000000..443d303c296
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/ha/EnableHAForZoneCmd.java
@@ -0,0 +1,115 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.api.command.admin.ha;
+
+import com.cloud.dc.DataCenter;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiArgValidator;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.ha.HAConfigManager;
+
+import javax.inject.Inject;
+
+@APICommand(name = EnableHAForZoneCmd.APINAME, description = "Enables HA for a zone",
+ responseObject = SuccessResponse.class,
+ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
+ since = "4.11", authorized = {RoleType.Admin})
+public final class EnableHAForZoneCmd extends BaseAsyncCmd {
+ public static final String APINAME = "enableHAForZone";
+
+ @Inject
+ private HAConfigManager haConfigManager;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.ZONE_ID, type = BaseCmd.CommandType.UUID, entityType = ZoneResponse.class,
+ description = "ID of the zone", required = true, validations = {ApiArgValidator.PositiveNumber})
+ private Long zoneId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getZoneId() {
+ return zoneId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccountId();
+ }
+
+ private void setupResponse(final boolean result) {
+ final SuccessResponse response = new SuccessResponse();
+ response.setSuccess(result);
+ response.setResponseName(getCommandName());
+ response.setObjectName("ha");
+ setResponseObject(response);
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
+ final DataCenter dataCenter = _resourceService.getZone(getZoneId());
+ if (dataCenter == null) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to find zone by ID: " + getZoneId());
+ }
+
+ final boolean result = haConfigManager.enableHA(dataCenter);
+ CallContext.current().setEventDetails("Zone Id:" + dataCenter.getId() + " HA enabled: true");
+ CallContext.current().putContextParameter(DataCenter.class, dataCenter.getUuid());
+
+ setupResponse(result);
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_HA_RESOURCE_ENABLE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "enable HA for zone: " + getZoneId();
+ }
+
+}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/ha/ListHostHAProvidersCmd.java b/api/src/org/apache/cloudstack/api/command/admin/ha/ListHostHAProvidersCmd.java
new file mode 100644
index 00000000000..64b9a6a8e5c
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/ha/ListHostHAProvidersCmd.java
@@ -0,0 +1,106 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.api.command.admin.ha;
+
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+import com.google.common.base.Enums;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiArgValidator;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.HAProviderResponse;
+import org.apache.cloudstack.api.response.HostHAResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.ha.HAConfigManager;
+import org.apache.cloudstack.ha.HAResource;
+
+import javax.inject.Inject;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@APICommand(name = ListHostHAProvidersCmd.APINAME, description = "Lists HA providers", responseObject = HostHAResponse.class,
+ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
+ since = "4.11", authorized = {RoleType.Admin})
+public final class ListHostHAProvidersCmd extends BaseCmd {
+ public static final String APINAME = "listHostHAProviders";
+
+ @Inject
+ private HAConfigManager haConfigManager;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.HYPERVISOR, type = CommandType.STRING, required = true,
+ description = "Hypervisor type of the resource", validations = {ApiArgValidator.NotNullOrEmpty})
+ private String hypervisorType;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public HAResource.ResourceSubType getHypervisorType() {
+ return HAResource.ResourceSubType.valueOf(hypervisorType);
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ private void setupResponse(final List<String> hostHAProviderList) {
+ final ListResponse<HAProviderResponse> response = new ListResponse<>();
+ final List<HAProviderResponse> hostHAResponses = new ArrayList<>();
+ for (final String provider : hostHAProviderList) {
+ final HAProviderResponse haProviderResponse = new HAProviderResponse();
+ haProviderResponse.setProvider(provider);
+ hostHAResponses.add(haProviderResponse);
+ }
+ response.setResponses(hostHAResponses);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
+ if (!Enums.getIfPresent(HAResource.ResourceSubType.class, hypervisorType).isPresent()) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Invalid or unsupported host hypervisor type provided. Supported types are: " + Arrays.toString(HAResource.ResourceSubType.values()));
+ }
+ final List<String> hostHAProviders = haConfigManager.listHAProviders(HAResource.ResourceType.Host, getHypervisorType());
+ setupResponse(hostHAProviders);
+ }
+}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/ha/ListHostHAResourcesCmd.java b/api/src/org/apache/cloudstack/api/command/admin/ha/ListHostHAResourcesCmd.java
new file mode 100644
index 00000000000..75a900c2198
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/ha/ListHostHAResourcesCmd.java
@@ -0,0 +1,109 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.api.command.admin.ha;
+
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.host.Host;
+import com.cloud.user.Account;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiArgValidator;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.HostHAResponse;
+import org.apache.cloudstack.api.response.HostResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.ha.HAConfig;
+import org.apache.cloudstack.ha.HAConfigManager;
+import org.apache.cloudstack.ha.HAResource;
+
+import javax.inject.Inject;
+import java.util.ArrayList;
+import java.util.List;
+
+@APICommand(name = ListHostHAResourcesCmd.APINAME, description = "Lists host HA resources", responseObject = HostHAResponse.class,
+ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
+ since = "4.11", authorized = {RoleType.Admin})
+public final class ListHostHAResourcesCmd extends BaseCmd {
+ public static final String APINAME = "listHostHAResources";
+
+ @Inject
+ private HAConfigManager haConfigManager;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.HOST_ID, type = CommandType.UUID, entityType = HostResponse.class,
+ description = "List by host ID", validations = {ApiArgValidator.PositiveNumber})
+ private Long hostId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getHostId() {
+ return hostId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ private void setupResponse(final List<HAConfig> hostHAConfigList) {
+ final ListResponse<HostHAResponse> response = new ListResponse<>();
+ final List<HostHAResponse> hostHAResponses = new ArrayList<>();
+ for (final HAConfig config : hostHAConfigList) {
+ final Host host = _resourceService.getHost(config.getResourceId());
+ if (host == null) {
+ continue;
+ }
+ final HostHAResponse hostHAResponse = new HostHAResponse();
+ hostHAResponse.setId(host.getUuid());
+ hostHAResponse.setEnabled(config.isEnabled());
+ hostHAResponse.setHaState(config.getState());
+ hostHAResponse.setProvider(config.getHaProvider());
+ hostHAResponses.add(hostHAResponse);
+ }
+ response.setResponses(hostHAResponses);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
+ final List<HAConfig> hostHAConfig = haConfigManager.listHAResources(getHostId(), HAResource.ResourceType.Host);
+ setupResponse(hostHAConfig);
+ }
+}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/host/UpdateHostCmd.java b/api/src/org/apache/cloudstack/api/command/admin/host/UpdateHostCmd.java
index c6f6530dc50..aa0a690e2a9 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/host/UpdateHostCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/host/UpdateHostCmd.java
@@ -16,10 +16,10 @@
// under the License.
package org.apache.cloudstack.api.command.admin.host;
-import java.util.List;
-
-import org.apache.log4j.Logger;
-
+import com.cloud.host.Host;
+import com.cloud.user.Account;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
@@ -28,9 +28,9 @@
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.GuestOSCategoryResponse;
import org.apache.cloudstack.api.response.HostResponse;
+import org.apache.log4j.Logger;
-import com.cloud.host.Host;
-import com.cloud.user.Account;
+import java.util.List;
@APICommand(name = "updateHost", description = "Updates a host.", responseObject = HostResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
@@ -62,6 +62,9 @@
@Parameter(name = ApiConstants.URL, type = CommandType.STRING, description = "the new uri for the secondary storage: nfs://host/path")
private String url;
+ @Parameter(name = ApiConstants.ANNOTATION, type = CommandType.STRING, description = "Add an annotation to this host", since = "4.11", authorized = {RoleType.Admin})
+ private String annotation;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -86,6 +89,10 @@ public String getUrl() {
return url;
}
+ public String getAnnotation() {
+ return annotation;
+ }
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@@ -109,6 +116,9 @@ public void execute() {
Host result;
try {
result = _resourceService.updateHost(this);
+ if(getAnnotation() != null) {
+ annotationService.addAnnotation(getAnnotation(), AnnotationService.EntityType.HOST, result.getUuid());
+ }
HostResponse hostResponse = _responseGenerator.createHostResponse(result);
hostResponse.setResponseName(getCommandName());
this.setResponseObject(hostResponse);
diff --git a/api/src/org/apache/cloudstack/api/command/admin/network/CreateNetworkCmdByAdmin.java b/api/src/org/apache/cloudstack/api/command/admin/network/CreateNetworkCmdByAdmin.java
index 6cf9e2308dc..6d346e9a4db 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/network/CreateNetworkCmdByAdmin.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/network/CreateNetworkCmdByAdmin.java
@@ -40,6 +40,9 @@
@Parameter(name=ApiConstants.VLAN, type=CommandType.STRING, description="the ID or VID of the network")
private String vlan;
+ @Parameter(name=ApiConstants.BYPASS_VLAN_OVERLAP_CHECK, type=CommandType.BOOLEAN, description="when true bypasses VLAN id/range overlap check during network creation for shared networks")
+ private Boolean bypassVlanOverlapCheck;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -48,6 +51,13 @@ public String getVlan() {
return vlan;
}
+ public Boolean getBypassVlanOverlapCheck() {
+ if (bypassVlanOverlapCheck != null) {
+ return bypassVlanOverlapCheck;
+ }
+ return false;
+ }
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
diff --git a/api/src/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java b/api/src/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java
index a09c9797b68..259c4905ed1 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java
@@ -113,7 +113,8 @@
private Boolean isPersistent;
@Parameter(name = ApiConstants.DETAILS, type = CommandType.MAP, since = "4.2.0", description = "Network offering details in key/value pairs."
- + " Supported keys are internallbprovider/publiclbprovider with service provider as a value")
+ + " Supported keys are internallbprovider/publiclbprovider with service provider as a value, and"
+ + " promiscuousmode/macaddresschanges/forgedtransmits with true/false as value to accept/reject the security settings if available for a nic/portgroup")
protected Map details;
@Parameter(name = ApiConstants.EGRESS_DEFAULT_POLICY,
@@ -273,10 +274,23 @@ public Integer getMaxconnections() {
}
Collection paramsCollection = details.values();
- Map<String, String> params = (Map<String, String>)(paramsCollection.toArray())[0];
+ Object objlist[]= paramsCollection.toArray();
+ Map<String, String> params = (Map<String, String>)(objlist[0]);
+ for(int i=1; i< objlist.length; i++)
+ {
+ params.putAll((Map<String, String>)(objlist[i]));
+ }
+
return params;
}
+ public String getServicePackageId() {
+ Map<String, String> data = getDetails();
+ if (data == null)
+ return null;
+ return data.get(NetworkOffering.Detail.servicepackageuuid+ "");
+ }
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
diff --git a/api/src/org/apache/cloudstack/api/command/admin/outofbandmanagement/ChangeOutOfBandManagementPasswordCmd.java b/api/src/org/apache/cloudstack/api/command/admin/outofbandmanagement/ChangeOutOfBandManagementPasswordCmd.java
index ea2e3cdb76b..0499a6e4577 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/outofbandmanagement/ChangeOutOfBandManagementPasswordCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/outofbandmanagement/ChangeOutOfBandManagementPasswordCmd.java
@@ -74,7 +74,7 @@ public void execute() throws ResourceUnavailableException, InsufficientCapacityE
CallContext.current().setEventDetails("Host Id: " + host.getId() + " Password: " + getPassword().charAt(0) + "****");
CallContext.current().putContextParameter(Host.class, host.getUuid());
- final OutOfBandManagementResponse response = outOfBandManagementService.changeOutOfBandManagementPassword(host, getPassword());
+ final OutOfBandManagementResponse response = outOfBandManagementService.changePassword(host, getPassword());
response.setResponseName(getCommandName());
setResponseObject(response);
}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/outofbandmanagement/ConfigureOutOfBandManagementCmd.java b/api/src/org/apache/cloudstack/api/command/admin/outofbandmanagement/ConfigureOutOfBandManagementCmd.java
index db224108df0..d9c6c9f439e 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/outofbandmanagement/ConfigureOutOfBandManagementCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/outofbandmanagement/ConfigureOutOfBandManagementCmd.java
@@ -83,7 +83,7 @@ public void execute() throws ResourceUnavailableException, InsufficientCapacityE
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to find host by ID: " + getHostId());
}
CallContext.current().putContextParameter(Host.class, host.getUuid());
- final OutOfBandManagementResponse response = outOfBandManagementService.configureOutOfBandManagement(host, getHostPMOptions());
+ final OutOfBandManagementResponse response = outOfBandManagementService.configure(host, getHostPMOptions());
response.setId(host.getUuid());
response.setResponseName(getCommandName());
setResponseObject(response);
diff --git a/api/src/org/apache/cloudstack/api/command/admin/outofbandmanagement/IssueOutOfBandManagementPowerActionCmd.java b/api/src/org/apache/cloudstack/api/command/admin/outofbandmanagement/IssueOutOfBandManagementPowerActionCmd.java
index 8d6bdd350d0..7593a3cbc52 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/outofbandmanagement/IssueOutOfBandManagementPowerActionCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/outofbandmanagement/IssueOutOfBandManagementPowerActionCmd.java
@@ -80,7 +80,7 @@ public void execute() throws ResourceUnavailableException, InsufficientCapacityE
CallContext.current().setEventDetails("Host Id: " + host.getId() + " Action: " + powerOperation.toString());
CallContext.current().putContextParameter(Host.class, host.getUuid());
- final OutOfBandManagementResponse response = outOfBandManagementService.executeOutOfBandManagementPowerOperation(host, powerOperation, getActionTimeout());
+ final OutOfBandManagementResponse response = outOfBandManagementService.executePowerOperation(host, powerOperation, getActionTimeout());
response.setResponseName(getCommandName());
setResponseObject(response);
}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/resource/ListCapacityCmd.java b/api/src/org/apache/cloudstack/api/command/admin/resource/ListCapacityCmd.java
index d79ff07fbcc..76ca3a79b11 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/resource/ListCapacityCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/resource/ListCapacityCmd.java
@@ -17,6 +17,8 @@
package org.apache.cloudstack.api.command.admin.resource;
import java.text.DecimalFormat;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import org.apache.log4j.Logger;
@@ -65,7 +67,8 @@
@Parameter(name = ApiConstants.TYPE, type = CommandType.INTEGER, description = "lists capacity by type" + "* CAPACITY_TYPE_MEMORY = 0" + "* CAPACITY_TYPE_CPU = 1"
+ "* CAPACITY_TYPE_STORAGE = 2" + "* CAPACITY_TYPE_STORAGE_ALLOCATED = 3" + "* CAPACITY_TYPE_VIRTUAL_NETWORK_PUBLIC_IP = 4" + "* CAPACITY_TYPE_PRIVATE_IP = 5"
- + "* CAPACITY_TYPE_SECONDARY_STORAGE = 6" + "* CAPACITY_TYPE_VLAN = 7" + "* CAPACITY_TYPE_DIRECT_ATTACHED_PUBLIC_IP = 8" + "* CAPACITY_TYPE_LOCAL_STORAGE = 9.")
+ + "* CAPACITY_TYPE_SECONDARY_STORAGE = 6" + "* CAPACITY_TYPE_VLAN = 7" + "* CAPACITY_TYPE_DIRECT_ATTACHED_PUBLIC_IP = 8" + "* CAPACITY_TYPE_LOCAL_STORAGE = 9"
+ + "* CAPACITY_TYPE_GPU = 19" + "* CAPACITY_TYPE_CPU_CORE = 90.")
private Integer type;
@Parameter(name = ApiConstants.SORT_BY, type = CommandType.STRING, since = "3.0.0", description = "Sort the results. Available values: Usage")
@@ -127,6 +130,17 @@ public void execute() {
ListResponse<CapacityResponse> response = new ListResponse<CapacityResponse>();
List<CapacityResponse> capacityResponses = _responseGenerator.createCapacityResponse(result, s_percentFormat);
+ Collections.sort(capacityResponses, new Comparator<CapacityResponse>() {
+ public int compare(CapacityResponse resp1, CapacityResponse resp2) {
+ int res = resp1.getZoneName().compareTo(resp2.getZoneName());
+ if (res != 0) {
+ return res;
+ } else {
+ return resp1.getCapacityType().compareTo(resp2.getCapacityType());
+ }
+ }
+ });
+
response.setResponses(capacityResponses);
response.setResponseName(getCommandName());
this.setResponseObject(response);
diff --git a/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java b/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java
index 75bd9d21d1b..15072ca9a4f 100644
--- a/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java
@@ -57,7 +57,7 @@
import com.cloud.projects.Project;
import com.cloud.user.Account;
-@APICommand(name = "associateIpAddress", description = "Acquires and associates a public IP to an account.", responseObject = IPAddressResponse.class, responseView = ResponseView.Restricted,
+@APICommand(name = "associateIpAddress", description = "Acquires and associates a public IP to an account. Either of the parameters are required, i.e. either zoneId, or networkId, or vpcId ", responseObject = IPAddressResponse.class, responseView = ResponseView.Restricted,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class AssociateIPAddrCmd extends BaseAsyncCreateCmd {
public static final Logger s_logger = Logger.getLogger(AssociateIPAddrCmd.class.getName());
diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/UpdatePortForwardingRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/UpdatePortForwardingRuleCmd.java
index 5f609b726f8..7de50761630 100644
--- a/api/src/org/apache/cloudstack/api/command/user/firewall/UpdatePortForwardingRuleCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/firewall/UpdatePortForwardingRuleCmd.java
@@ -47,9 +47,13 @@
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = FirewallRuleResponse.class, required = true, description = "the ID of the port forwarding rule", since = "4.4")
private Long id;
- @Parameter(name=ApiConstants.PRIVATE_PORT, type=CommandType.INTEGER, description="the private port of the port forwarding rule")
+ @Parameter(name=ApiConstants.PRIVATE_START_PORT, type=CommandType.INTEGER, description="the private start port of the port forwarding rule")
private Integer privatePort;
+
+ @Parameter(name=ApiConstants.PRIVATE_END_PORT, type=CommandType.INTEGER, description="the private end port of the port forwarding rule")
+ private Integer privateEndPort;
+
@Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID,
type = CommandType.UUID,
entityType = UserVmResponse.class,
@@ -74,6 +78,10 @@ public Integer getPrivatePort() {
return privatePort;
}
+ public Integer getPrivateEndPort() {
+ return privateEndPort;
+ }
+
public Long getVirtualMachineId() {
return virtualMachineId;
}
@@ -130,7 +138,7 @@ public void checkUuid() {
@Override
public void execute() {
- PortForwardingRule rule = _rulesService.updatePortForwardingRule(id, getPrivatePort(), getVirtualMachineId(), getVmGuestIp(), getCustomId(), getDisplay());
+ PortForwardingRule rule = _rulesService.updatePortForwardingRule(getId(), getPrivatePort(), getPrivateEndPort(), getVirtualMachineId(), getVmGuestIp(), getCustomId(), getDisplay());
FirewallRuleResponse fwResponse = new FirewallRuleResponse();
if (rule != null) {
fwResponse = _responseGenerator.createPortForwardingRuleResponse(rule);
diff --git a/api/src/org/apache/cloudstack/api/command/user/iso/RegisterIsoCmd.java b/api/src/org/apache/cloudstack/api/command/user/iso/RegisterIsoCmd.java
index 599aac1fd03..3112287fb9c 100644
--- a/api/src/org/apache/cloudstack/api/command/user/iso/RegisterIsoCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/iso/RegisterIsoCmd.java
@@ -94,7 +94,7 @@
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "an optional account name. Must be used with domainId.")
private String accountName;
- @Parameter(name = ApiConstants.CHECKSUM, type = CommandType.STRING, description = "the MD5 checksum value of this ISO")
+ @Parameter(name = ApiConstants.CHECKSUM, type = CommandType.STRING, description = "the checksum value of this ISO. " + ApiConstants.CHECKSUM_PARAMETER_PREFIX_DESCRIPTION)
private String checksum;
@Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, entityType = ProjectResponse.class, description = "Register ISO for the project")
diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/UpdateLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/UpdateLoadBalancerRuleCmd.java
index 6b1e0fddd54..6ee277a354c 100644
--- a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/UpdateLoadBalancerRuleCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/UpdateLoadBalancerRuleCmd.java
@@ -64,6 +64,9 @@
@Parameter(name = ApiConstants.FOR_DISPLAY, type = CommandType.BOOLEAN, description = "an optional field, whether to the display the rule to the end user or not", since = "4.4", authorized = {RoleType.Admin})
private Boolean display;
+ @Parameter(name = ApiConstants.PROTOCOL, type = CommandType.STRING, description = "The protocol for the LB")
+ private String lbProtocol;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -88,6 +91,10 @@ public Boolean getDisplay() {
return display;
}
+ public String getLbProtocol() {
+ return lbProtocol;
+ }
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/UploadSslCertCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/UploadSslCertCmd.java
index a6d71c76175..309e43fcbbe 100644
--- a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/UploadSslCertCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/UploadSslCertCmd.java
@@ -73,6 +73,9 @@
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, description = "domain ID of the account owning the SSL certificate")
private Long domainId;
+ @Parameter(name = ApiConstants.NAME , type = CommandType.STRING, required = true, description = "Name for the uploaded certificate")
+ private String name;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -105,10 +108,15 @@ public Long getProjectId() {
return projectId;
}
+ public String getName() {
+ return name;
+ }
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
+
@Override
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
ResourceAllocationException, NetworkRuleConflictException {
diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java
index e79feb75632..d66b6499399 100644
--- a/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java
@@ -79,6 +79,9 @@
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "the name of the snapshot")
private String snapshotName;
+ @Parameter(name = ApiConstants.ASYNC_BACKUP, type = CommandType.BOOLEAN, required = false, description = "asynchronous backup if true")
+ private Boolean asyncBackup;
+
private String syncObjectType = BaseAsyncCmd.snapshotHostSyncObject;
// ///////////////////////////////////////////////////
@@ -200,7 +203,7 @@ public void execute() {
Snapshot snapshot;
try {
snapshot =
- _volumeService.takeSnapshot(getVolumeId(), getPolicyId(), getEntityId(), _accountService.getAccount(getEntityOwnerId()), getQuiescevm(), getLocationType());
+ _volumeService.takeSnapshot(getVolumeId(), getPolicyId(), getEntityId(), _accountService.getAccount(getEntityOwnerId()), getQuiescevm(), getLocationType(), getAsyncBackup());
if (snapshot != null) {
SnapshotResponse response = _responseGenerator.createSnapshotResponse(snapshot);
@@ -246,4 +249,12 @@ public Long getSyncObjId() {
}
return null;
}
+
+ public Boolean getAsyncBackup() {
+ if (asyncBackup == null) {
+ return false;
+ } else {
+ return asyncBackup;
+ }
+ }
}
diff --git a/api/src/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java
index aff9d464a61..2bd7b2d38d1 100644
--- a/api/src/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java
@@ -122,7 +122,7 @@
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "an optional accountName. Must be used with domainId.")
private String accountName;
- @Parameter(name = ApiConstants.CHECKSUM, type = CommandType.STRING, description = "the MD5 checksum value of this template")
+ @Parameter(name = ApiConstants.CHECKSUM, type = CommandType.STRING, description = "the checksum value of this template. " + ApiConstants.CHECKSUM_PARAMETER_PREFIX_DESCRIPTION)
private String checksum;
@Parameter(name = ApiConstants.TEMPLATE_TAG, type = CommandType.STRING, description = "the tag for this template.")
@@ -148,7 +148,6 @@
collectionType = CommandType.UUID,
entityType = ZoneResponse.class,
required=false,
- since="4.10.0.0",
description="A list of zone ids where the template will be hosted. Use this parameter if the template needs " +
"to be registered to multiple zones in one go. Use zoneid if the template " +
"needs to be registered to only one zone." +
diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/AddNicToVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/AddNicToVMCmd.java
index f265ecf236a..ef03e78bea5 100644
--- a/api/src/org/apache/cloudstack/api/command/user/vm/AddNicToVMCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/vm/AddNicToVMCmd.java
@@ -36,8 +36,10 @@
import org.apache.cloudstack.context.CallContext;
import com.cloud.event.EventTypes;
+import com.cloud.exception.InvalidParameterValueException;
import com.cloud.user.Account;
import com.cloud.uservm.UserVm;
+import com.cloud.utils.net.NetUtils;
import com.cloud.vm.VirtualMachine;
@APICommand(name = "addNicToVirtualMachine", description = "Adds VM to specified network by creating a NIC", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class},
@@ -60,6 +62,9 @@
@Parameter(name = ApiConstants.IP_ADDRESS, type = CommandType.STRING, description = "IP Address for the new network")
private String ipaddr;
+ @Parameter(name = ApiConstants.MAC_ADDRESS, type = CommandType.STRING, description = "Mac Address for the new network")
+ private String macaddr;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -76,6 +81,18 @@ public String getIpAddress() {
return ipaddr;
}
+ public String getMacAddress() {
+ if (macaddr == null) {
+ return null;
+ }
+ if(!NetUtils.isValidMac(macaddr)) {
+ throw new InvalidParameterValueException("Mac address is not valid: " + macaddr);
+ } else if(!NetUtils.isUnicastMac(macaddr)) {
+ throw new InvalidParameterValueException("Mac address is not unicast: " + macaddr);
+ }
+ return NetUtils.standardizeMacAddress(macaddr);
+ }
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java
index da0ce2a2ff9..bd2ae6f9c17 100644
--- a/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java
@@ -147,7 +147,7 @@
private List<String> securityGroupNameList;
@Parameter(name = ApiConstants.IP_NETWORK_LIST, type = CommandType.MAP, description = "ip to network mapping. Can't be specified with networkIds parameter."
- + " Example: iptonetworklist[0].ip=10.10.10.11&iptonetworklist[0].ipv6=fc00:1234:5678::abcd&iptonetworklist[0].networkid=uuid - requests to use ip 10.10.10.11 in network id=uuid")
+ + " Example: iptonetworklist[0].ip=10.10.10.11&iptonetworklist[0].ipv6=fc00:1234:5678::abcd&iptonetworklist[0].networkid=uuid&iptonetworklist[0].mac=aa:bb:cc:dd:ee::ff - requests to use ip 10.10.10.11 in network id=uuid")
private Map ipToNetworkList;
@Parameter(name = ApiConstants.IP_ADDRESS, type = CommandType.STRING, description = "the ip address for default vm's network")
@@ -156,6 +156,9 @@
@Parameter(name = ApiConstants.IP6_ADDRESS, type = CommandType.STRING, description = "the ipv6 address for default vm's network")
private String ip6Address;
+ @Parameter(name = ApiConstants.MAC_ADDRESS, type = CommandType.STRING, description = "the mac address for default vm's network")
+ private String macAddress;
+
@Parameter(name = ApiConstants.KEYBOARD, type = CommandType.STRING, description = "an optional keyboard device type for the virtual machine. valid value can be one of de,de-ch,es,fi,fr,fr-be,fr-ch,is,it,jp,nl-be,no,pt,uk,us")
private String keyboard;
@@ -333,10 +336,19 @@ public boolean getStartVm() {
}
String requestedIp = ips.get("ip");
String requestedIpv6 = ips.get("ipv6");
+ String requestedMac = ips.get("mac");
if (requestedIpv6 != null) {
requestedIpv6 = NetUtils.standardizeIp6Address(requestedIpv6);
}
- IpAddresses addrs = new IpAddresses(requestedIp, requestedIpv6);
+ if (requestedMac != null) {
+ if(!NetUtils.isValidMac(requestedMac)) {
+ throw new InvalidParameterValueException("Mac address is not valid: " + requestedMac);
+ } else if(!NetUtils.isUnicastMac(requestedMac)) {
+ throw new InvalidParameterValueException("Mac address is not unicast: " + requestedMac);
+ }
+ requestedMac = NetUtils.standardizeMacAddress(requestedMac);
+ }
+ IpAddresses addrs = new IpAddresses(requestedIp, requestedIpv6, requestedMac);
ipToNetworkMap.put(networkId, addrs);
}
}
@@ -355,6 +367,19 @@ public String getIp6Address() {
return NetUtils.standardizeIp6Address(ip6Address);
}
+
+ public String getMacAddress() {
+ if (macAddress == null) {
+ return null;
+ }
+ if(!NetUtils.isValidMac(macAddress)) {
+ throw new InvalidParameterValueException("Mac address is not valid: " + macAddress);
+ } else if(!NetUtils.isUnicastMac(macAddress)) {
+ throw new InvalidParameterValueException("Mac address is not unicast: " + macAddress);
+ }
+ return NetUtils.standardizeMacAddress(macAddress);
+ }
+
public List<Long> getAffinityGroupIdList() {
if (affinityGroupNameList != null && affinityGroupIdList != null) {
throw new InvalidParameterValueException("affinitygroupids parameter is mutually exclusive with affinitygroupnames parameter");
diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java
index 21749616753..a48a89b79b4 100644
--- a/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java
@@ -82,7 +82,7 @@
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "an optional accountName. Must be used with domainId.")
private String accountName;
- @Parameter(name = ApiConstants.CHECKSUM, type = CommandType.STRING, description = "the MD5 checksum value of this volume")
+ @Parameter(name = ApiConstants.CHECKSUM, type = CommandType.STRING, description = "the checksum value of this volume. " + ApiConstants.CHECKSUM_PARAMETER_PREFIX_DESCRIPTION)
private String checksum;
@Parameter(name = ApiConstants.IMAGE_STORE_UUID, type = CommandType.STRING, description = "Image store uuid")
diff --git a/api/src/org/apache/cloudstack/api/response/AcquireIPAddressResponse.java b/api/src/org/apache/cloudstack/api/response/AcquireIPAddressResponse.java
new file mode 100644
index 00000000000..70cbd7ffe05
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/response/AcquireIPAddressResponse.java
@@ -0,0 +1,286 @@
+//Licensed to the Apache Software Foundation (ASF) under one
+//or more contributor license agreements. See the NOTICE file
+//distributed with this work for additional information
+//regarding copyright ownership. The ASF licenses this file
+//to you under the Apache License, Version 2.0 (the
+//"License"); you may not use this file except in compliance
+//with the License. You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing,
+//software distributed under the License is distributed on an
+//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+//KIND, either express or implied. See the License for the
+//specific language governing permissions and limitations
+//under the License.
+package org.apache.cloudstack.api.response;
+
+import java.util.Date;
+import java.util.List;
+
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseResponse;
+import org.apache.cloudstack.api.EntityReference;
+
+import com.cloud.network.IpAddress;
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+@EntityReference(value = IpAddress.class)
+@SuppressWarnings("unused")
+public class AcquireIPAddressResponse extends BaseResponse implements ControlledEntityResponse {
+ @SerializedName(ApiConstants.ID)
+ @Param(description = "public IP address id")
+ private String id;
+
+ @SerializedName(ApiConstants.IP_ADDRESS)
+ @Param(description = "public IP address")
+ private String ipAddress;
+
+ @SerializedName("allocated")
+ @Param(description = "date the public IP address was acquired")
+ private Date allocated;
+
+ @SerializedName(ApiConstants.ZONE_ID)
+ @Param(description = "the ID of the zone the public IP address belongs to")
+ private String zoneId;
+
+ @SerializedName(ApiConstants.ZONE_NAME)
+ @Param(description = "the name of the zone the public IP address belongs to")
+ private String zoneName;
+
+ @SerializedName("issourcenat")
+ @Param(description = "true if the IP address is a source nat address, false otherwise")
+ private Boolean sourceNat;
+
+ @SerializedName(ApiConstants.ACCOUNT)
+ @Param(description = "the account the public IP address is associated with")
+ private String accountName;
+
+ @SerializedName(ApiConstants.PROJECT_ID)
+ @Param(description = "the project id of the ipaddress")
+ private String projectId;
+
+ @SerializedName(ApiConstants.PROJECT)
+ @Param(description = "the project name of the address")
+ private String projectName;
+
+ @SerializedName(ApiConstants.DOMAIN_ID)
+ @Param(description = "the domain ID the public IP address is associated with")
+ private String domainId;
+
+ @SerializedName(ApiConstants.DOMAIN)
+ @Param(description = "the domain the public IP address is associated with")
+ private String domainName;
+
+ @SerializedName(ApiConstants.FOR_VIRTUAL_NETWORK)
+ @Param(description = "the virtual network for the IP address")
+ private Boolean forVirtualNetwork;
+
+ @SerializedName(ApiConstants.VLAN_ID)
+ @Param(description = "the ID of the VLAN associated with the IP address." + " This parameter is visible to ROOT admins only")
+ private String vlanId;
+
+ @SerializedName("vlanname")
+ @Param(description = "the VLAN associated with the IP address")
+ private String vlanName;
+
+ @SerializedName("isstaticnat")
+ @Param(description = "true if this ip is for static nat, false otherwise")
+ private Boolean staticNat;
+
+ @SerializedName(ApiConstants.IS_SYSTEM)
+ @Param(description = "true if this ip is system ip (was allocated as a part of deployVm or createLbRule)")
+ private Boolean isSystem;
+
+ @SerializedName(ApiConstants.VIRTUAL_MACHINE_ID)
+ @Param(description = "virutal machine id the ip address is assigned to (not null only for static nat Ip)")
+ private String virtualMachineId;
+
+ @SerializedName("vmipaddress")
+ @Param(description = "virutal machine (dnat) ip address (not null only for static nat Ip)")
+ private String virtualMachineIp;
+
+ @SerializedName("virtualmachinename")
+ @Param(description = "virutal machine name the ip address is assigned to (not null only for static nat Ip)")
+ private String virtualMachineName;
+
+ @SerializedName("virtualmachinedisplayname")
+ @Param(description = "virutal machine display name the ip address is assigned to (not null only for static nat Ip)")
+ private String virtualMachineDisplayName;
+
+ @SerializedName(ApiConstants.ASSOCIATED_NETWORK_ID)
+ @Param(description = "the ID of the Network associated with the IP address")
+ private String associatedNetworkId;
+
+ @SerializedName(ApiConstants.ASSOCIATED_NETWORK_NAME)
+ @Param(description = "the name of the Network associated with the IP address")
+ private String associatedNetworkName;
+
+ @SerializedName(ApiConstants.NETWORK_ID)
+ @Param(description = "the ID of the Network where ip belongs to")
+ private String networkId;
+
+ @SerializedName(ApiConstants.STATE)
+ @Param(description = "State of the ip address. Can be: Allocatin, Allocated and Releasing")
+ private String state;
+
+ @SerializedName(ApiConstants.PHYSICAL_NETWORK_ID)
+ @Param(description = "the physical network this belongs to")
+ private String physicalNetworkId;
+
+ @SerializedName(ApiConstants.PURPOSE)
+ @Param(description = "purpose of the IP address. In Acton this value is not null for Ips with isSystem=true, and can have either StaticNat or LB value")
+ private String purpose;
+
+ @SerializedName(ApiConstants.VPC_ID)
+ @Param(description = "VPC the ip belongs to")
+ private String vpcId;
+ @SerializedName(ApiConstants.TAGS)
+ @Param(description = "the list of resource tags associated with ip address", responseObject = ResourceTagResponse.class)
+ private List<ResourceTagResponse> tags;
+
+ @SerializedName(ApiConstants.IS_PORTABLE)
+ @Param(description = "is public IP portable across the zones")
+ private Boolean isPortable;
+
+ @SerializedName(ApiConstants.FOR_DISPLAY)
+ @Param(description = "is public ip for display to the regular user", since = "4.4", authorized = {RoleType.Admin})
+ private Boolean forDisplay;
+
+ public void setIpAddress(String ipAddress) {
+ this.ipAddress = ipAddress;
+ }
+
+ @Override
+ public String getObjectId() {
+ return this.getId();
+ }
+
+ public void setAllocated(Date allocated) {
+ this.allocated = allocated;
+ }
+
+ public void setZoneId(String zoneId) {
+ this.zoneId = zoneId;
+ }
+
+ public void setZoneName(String zoneName) {
+ this.zoneName = zoneName;
+ }
+
+ public void setSourceNat(Boolean sourceNat) {
+ this.sourceNat = sourceNat;
+ }
+
+ @Override
+ public void setAccountName(String accountName) {
+ this.accountName = accountName;
+ }
+
+ @Override
+ public void setDomainId(String domainId) {
+ this.domainId = domainId;
+ }
+
+ @Override
+ public void setDomainName(String domainName) {
+ this.domainName = domainName;
+ }
+
+ public void setForVirtualNetwork(Boolean forVirtualNetwork) {
+ this.forVirtualNetwork = forVirtualNetwork;
+ }
+
+ public void setVlanId(String vlanId) {
+ this.vlanId = vlanId;
+ }
+
+ public void setVlanName(String vlanName) {
+ this.vlanName = vlanName;
+ }
+
+ public void setStaticNat(Boolean staticNat) {
+ this.staticNat = staticNat;
+ }
+
+ public void setAssociatedNetworkId(String networkId) {
+ this.associatedNetworkId = networkId;
+ }
+
+ public void setNetworkId(String networkId) {
+ this.networkId = networkId;
+ }
+
+ public void setVirtualMachineId(String virtualMachineId) {
+ this.virtualMachineId = virtualMachineId;
+ }
+
+ public void setVirtualMachineIp(String virtualMachineIp) {
+ this.virtualMachineIp = virtualMachineIp;
+ }
+
+ public void setVirtualMachineName(String virtualMachineName) {
+ this.virtualMachineName = virtualMachineName;
+ }
+
+ public void setVirtualMachineDisplayName(String virtualMachineDisplayName) {
+ this.virtualMachineDisplayName = virtualMachineDisplayName;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public void setState(String state) {
+ this.state = state;
+ }
+
+ @Override
+ public void setProjectId(String projectId) {
+ this.projectId = projectId;
+ }
+
+ @Override
+ public void setProjectName(String projectName) {
+ this.projectName = projectName;
+ }
+
+ public void setPhysicalNetworkId(String physicalNetworkId) {
+ this.physicalNetworkId = physicalNetworkId;
+ }
+
+ public void setIsSystem(Boolean isSystem) {
+ this.isSystem = isSystem;
+ }
+
+ public void setPurpose(String purpose) {
+ this.purpose = purpose;
+ }
+
+ public void setVpcId(String vpcId) {
+ this.vpcId = vpcId;
+ }
+
+ public void setTags(List<ResourceTagResponse> tags) {
+ this.tags = tags;
+ }
+
+ public void setAssociatedNetworkName(String associatedNetworkName) {
+ this.associatedNetworkName = associatedNetworkName;
+ }
+
+ public void setPortable(Boolean portable) {
+ this.isPortable = portable;
+ }
+
+ public void setForDisplay(Boolean forDisplay) {
+ this.forDisplay = forDisplay;
+ }
+}
diff --git a/api/src/org/apache/cloudstack/api/response/AcquirePodIpCmdResponse.java b/api/src/org/apache/cloudstack/api/response/AcquirePodIpCmdResponse.java
new file mode 100644
index 00000000000..3eece1d7afb
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/response/AcquirePodIpCmdResponse.java
@@ -0,0 +1,113 @@
+//Licensed to the Apache Software Foundation (ASF) under one
+//or more contributor license agreements. See the NOTICE file
+//distributed with this work for additional information
+//regarding copyright ownership. The ASF licenses this file
+//to you under the Apache License, Version 2.0 (the
+//"License"); you may not use this file except in compliance
+//with the License. You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing,
+//software distributed under the License is distributed on an
+//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+//KIND, either express or implied. See the License for the
+//specific language governing permissions and limitations
+//under the License.
+
+package org.apache.cloudstack.api.response;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseResponse;
+
+import com.cloud.serializer.Param;
+
+public class AcquirePodIpCmdResponse extends BaseResponse {
+
+ @SerializedName(ApiConstants.IP_ADDRESS)
+ @Param(description = "Allocated IP address")
+ private String ipAddress;
+
+ @SerializedName(ApiConstants.POD_ID)
+ @Param(description = "the ID of the pod the IP address belongs to")
+ private Long podId;
+
+ @SerializedName(ApiConstants.GATEWAY)
+ @Param(description = "Gateway for Pod ")
+ private String gateway;
+
+ @SerializedName(ApiConstants.CIDR)
+ @Param(description = "CIDR of the Pod")
+ private String cidrAddress;
+
+ @SerializedName(ApiConstants.NIC_ID)
+ @Param(description = "the ID of the nic")
+ private Long instanceId;
+
+ @SerializedName(ApiConstants.HOST_MAC)
+ @Param(description = "MAC address of the pod the IP")
+ private Long macAddress;
+
+ @SerializedName(ApiConstants.ID)
+ @Param(description = "the ID of the pod the IP address")
+ private long id;
+
+ public void setIpAddress(String ipAddress) {
+ this.ipAddress = ipAddress;
+ }
+
+ public void setInstanceId(Long instanceId) {
+ this.instanceId = instanceId;
+ }
+
+ public void setPodId(long podId) {
+ this.podId = podId;
+ }
+
+ public void setMacAddress(long macAddress) {
+ this.macAddress = macAddress;
+ }
+
+ public void setGateway(String gateway) {
+ this.gateway = gateway;
+ }
+
+ public void setCidrAddress(String cidrAddress) {
+ this.cidrAddress = cidrAddress;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public Long getInstanceId() {
+ return instanceId;
+ }
+
+ public long getPodId() {
+ return podId;
+ }
+
+ public String getIpAddress() {
+ return ipAddress;
+ }
+
+ public long getMacAddress() {
+ return macAddress;
+ }
+
+ public String getCidrAddress() {
+ return cidrAddress;
+ }
+
+ public String getGateway() {
+ return gateway;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+}
\ No newline at end of file
diff --git a/api/src/org/apache/cloudstack/api/response/AnnotationResponse.java b/api/src/org/apache/cloudstack/api/response/AnnotationResponse.java
new file mode 100644
index 00000000000..c16971ae7f3
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/response/AnnotationResponse.java
@@ -0,0 +1,121 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.response;
+
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+import org.apache.cloudstack.annotation.Annotation;
+import org.apache.cloudstack.annotation.AnnotationService;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseResponse;
+import org.apache.cloudstack.api.EntityReference;
+
+import java.util.Date;
+
+/**
+ * @since 4.11
+ */
+@EntityReference(value = Annotation.class)
+public class AnnotationResponse extends BaseResponse {
+ @SerializedName(ApiConstants.ID)
+ @Param(description = "the (uu)id of the annotation")
+ private String uuid;
+
+ @SerializedName(ApiConstants.ENTITY_TYPE)
+ @Param(description = "the type of the annotated entity")
+ private String entityType;
+
+ @SerializedName(ApiConstants.ENTITY_ID)
+ @Param(description = "the (uu)id of the entitiy to which this annotation pertains")
+ private String entityUuid;
+
+ @SerializedName(ApiConstants.ANNOTATION)
+ @Param(description = "the contents of the annotation")
+ private String annotation;
+
+ @SerializedName(ApiConstants.USER_ID)
+ @Param(description = "The (uu)id of the user that entered the annotation")
+ private String userUuid;
+
+ @SerializedName(ApiConstants.CREATED)
+ @Param(description = "the creation timestamp for this annotation")
+ private Date created;
+
+ @SerializedName(ApiConstants.REMOVED)
+ @Param(description = "the removal timestamp for this annotation")
+ private Date removed;
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
+ public String getEntityType() {
+ return entityType;
+ }
+
+ public void setEntityType(String entityType) {
+ this.entityType = entityType;
+ }
+
+ public void setEntityType(AnnotationService.EntityType entityType) {
+ this.entityType = entityType.toString();
+ }
+
+ public String getEntityUuid() {
+ return entityUuid;
+ }
+
+ public void setEntityUuid(String entityUuid) {
+ this.entityUuid = entityUuid;
+ }
+
+ public String getAnnotation() {
+ return annotation;
+ }
+
+ public void setAnnotation(String annotation) {
+ this.annotation = annotation;
+ }
+
+ public String getUserUuid() {
+ return userUuid;
+ }
+
+ public void setUserUuid(String userUuid) {
+ this.userUuid = userUuid;
+ }
+
+ public Date getCreated() {
+ return created;
+ }
+
+ public void setCreated(Date created) {
+ this.created = created;
+ }
+
+ public Date getRemoved() {
+ return removed;
+ }
+
+ public void setRemoved(Date removed) {
+ this.removed = removed;
+ }
+}
diff --git a/api/src/org/apache/cloudstack/api/response/CAProviderResponse.java b/api/src/org/apache/cloudstack/api/response/CAProviderResponse.java
new file mode 100644
index 00000000000..94d5882e18a
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/response/CAProviderResponse.java
@@ -0,0 +1,52 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.api.response;
+
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseResponse;
+import org.apache.cloudstack.api.EntityReference;
+import org.apache.cloudstack.framework.ca.CAProvider;
+
+@EntityReference(value = CAProvider.class)
+public class CAProviderResponse extends BaseResponse {
+ @SerializedName(ApiConstants.NAME)
+ @Param(description = "the CA service provider name")
+ private String name;
+
+ @SerializedName(ApiConstants.DESCRIPTION)
+ @Param(description = "the description of the CA service provider")
+ private String description;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+}
diff --git a/api/src/org/apache/cloudstack/api/response/CapacityResponse.java b/api/src/org/apache/cloudstack/api/response/CapacityResponse.java
index 460e4af8926..e9724497c38 100644
--- a/api/src/org/apache/cloudstack/api/response/CapacityResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/CapacityResponse.java
@@ -28,6 +28,10 @@
@Param(description = "the capacity type")
private Short capacityType;
+ @SerializedName(ApiConstants.NAME)
+ @Param(description="the capacity name")
+ private String capacityName;
+
@SerializedName(ApiConstants.ZONE_ID)
@Param(description = "the Zone ID")
private String zoneId;
@@ -52,6 +56,10 @@
@Param(description = "the Cluster name")
private String clusterName;
+ @SerializedName("capacityallocated")
+ @Param(description="the capacity currently in allocated")
+ private Long capacityAllocated;
+
@SerializedName("capacityused")
@Param(description = "the capacity currently in use")
private Long capacityUsed;
@@ -72,6 +80,14 @@ public void setCapacityType(Short capacityType) {
this.capacityType = capacityType;
}
+ public String getCapacityName() {
+ return capacityName;
+ }
+
+ public void setCapacityName(String capacityName) {
+ this.capacityName = capacityName;
+ }
+
public String getZoneId() {
return zoneId;
}
@@ -120,6 +136,14 @@ public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
+ public Long getCapacityAllocated() {
+ return capacityAllocated;
+ }
+
+ public void setCapacityAllocated(Long capacityAllocated) {
+ this.capacityAllocated = capacityAllocated;
+ }
+
public Long getCapacityUsed() {
return capacityUsed;
}
diff --git a/api/src/org/apache/cloudstack/api/response/CertificateResponse.java b/api/src/org/apache/cloudstack/api/response/CertificateResponse.java
new file mode 100644
index 00000000000..f8c3ecc7404
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/response/CertificateResponse.java
@@ -0,0 +1,58 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.api.response;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseResponse;
+
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+public class CertificateResponse extends BaseResponse {
+ @SerializedName(ApiConstants.CERTIFICATE)
+ @Param(description = "The client certificate")
+ private String certificate = "";
+
+ @SerializedName(ApiConstants.PRIVATE_KEY)
+ @Param(description = "Private key for the certificate")
+ private String privateKey;
+
+ @SerializedName(ApiConstants.CA_CERTIFICATES)
+ @Param(description = "The CA certificate(s)")
+ private String caCertificate;
+
+ public CertificateResponse() {
+ setObjectName("certificates");
+ }
+
+ public CertificateResponse(final String objectName) {
+ setObjectName(objectName);
+ }
+
+ public void setCertificate(final String certificate) {
+ this.certificate = certificate;
+ }
+
+ public void setPrivateKey(final String privateKey) {
+ this.privateKey = privateKey;
+ }
+
+ public void setCaCertificate(final String caCertificate) {
+ this.caCertificate = caCertificate;
+ }
+}
diff --git a/api/src/org/apache/cloudstack/api/response/HAProviderResponse.java b/api/src/org/apache/cloudstack/api/response/HAProviderResponse.java
new file mode 100644
index 00000000000..d75cbc3e120
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/response/HAProviderResponse.java
@@ -0,0 +1,58 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.api.response;
+
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseResponse;
+import org.apache.cloudstack.api.EntityReference;
+import org.apache.cloudstack.ha.HAConfig;
+
+import java.util.List;
+
+@EntityReference(value = HAConfig.class)
+public final class HAProviderResponse extends BaseResponse {
+ @SerializedName(ApiConstants.HA_PROVIDER)
+ @Param(description = "the HA provider")
+ private String provider;
+
+ @SerializedName(ApiConstants.TYPE)
+ @Param(description = "the HA provider resource type detail")
+ private List<String> supportedResourceTypes;
+
+ public HAProviderResponse() {
+ super("haprovider");
+ }
+
+ public String getProvider() {
+ return provider;
+ }
+
+ public void setProvider(String provider) {
+ this.provider = provider;
+ }
+
+ public List<String> getSupportedResourceTypes() {
+ return supportedResourceTypes;
+ }
+
+ public void setSupportedResourceTypes(List<String> supportedResourceTypes) {
+ this.supportedResourceTypes = supportedResourceTypes;
+ }
+}
diff --git a/api/src/org/apache/cloudstack/api/response/HostHAResponse.java b/api/src/org/apache/cloudstack/api/response/HostHAResponse.java
new file mode 100644
index 00000000000..942250cbc21
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/response/HostHAResponse.java
@@ -0,0 +1,104 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.api.response;
+
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseResponse;
+import org.apache.cloudstack.api.EntityReference;
+import org.apache.cloudstack.ha.HAConfig;
+
+@EntityReference(value = HAConfig.class)
+public final class HostHAResponse extends BaseResponse {
+ @SerializedName(ApiConstants.HOST_ID)
+ @Param(description = "the ID of the host")
+ private String id;
+
+ @SerializedName(ApiConstants.HA_ENABLE)
+ @Param(description = "if host HA is enabled for the host")
+ private Boolean enabled;
+
+ @SerializedName(ApiConstants.HA_STATE)
+ @Param(description = "the HA state of the host")
+ private HAConfig.HAState haState;
+
+ @SerializedName(ApiConstants.HA_PROVIDER)
+ @Param(description = "the host HA provider")
+ private String provider;
+
+ @SerializedName(ApiConstants.STATUS)
+ @Param(description = "operation status")
+ private Boolean status;
+
+ public HostHAResponse() {
+ super("hostha");
+ }
+
+ public HostHAResponse(final HAConfig config) {
+ this();
+ if (config == null) {
+ this.enabled = false;
+ this.haState = HAConfig.HAState.Disabled;
+ return;
+ }
+ setProvider(config.getHaProvider());
+ setEnabled(config.isEnabled());
+ setHaState(config.getState());
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public Boolean getEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(Boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public HAConfig.HAState getHaState() {
+ return haState;
+ }
+
+ public void setHaState(HAConfig.HAState haState) {
+ this.haState = haState;
+ }
+
+ public String getProvider() {
+ return provider;
+ }
+
+ public void setProvider(String provider) {
+ this.provider = provider;
+ }
+
+ public Boolean getStatus() {
+ return status;
+ }
+
+ public void setStatus(Boolean status) {
+ this.status = status;
+ }
+}
diff --git a/api/src/org/apache/cloudstack/api/response/HostResponse.java b/api/src/org/apache/cloudstack/api/response/HostResponse.java
index 1a3a80ce0bf..b9667eca241 100644
--- a/api/src/org/apache/cloudstack/api/response/HostResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/HostResponse.java
@@ -24,6 +24,7 @@
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference;
+import org.apache.cloudstack.ha.HAConfig;
import org.apache.cloudstack.outofbandmanagement.OutOfBandManagement;
import java.util.Date;
@@ -206,6 +207,10 @@
@Param(description = "true if this host is suitable(has enough capacity and satisfies all conditions like hosttags, max guests vm limit etc) to migrate a VM to it , false otherwise")
private Boolean suitableForMigration;
+ @SerializedName("hostha")
+ @Param(description = "the host HA information information")
+ private HostHAResponse hostHAResponse;
+
@SerializedName("outofbandmanagement")
@Param(description = "the host out-of-band management information")
private OutOfBandManagementResponse outOfBandManagementResponse;
@@ -226,6 +231,17 @@
@Param(description = "Host details in key/value pairs.", since = "4.5")
private Map details;
+ @SerializedName(ApiConstants.ANNOTATION)
+ @Param(description = "the last annotation set on this host by an admin", since = "4.11")
+ private String annotation;
+
+ @SerializedName(ApiConstants.LAST_ANNOTATED)
+ @Param(description = "the last time this host was annotated", since = "4.11")
+ private Date lastAnnotated;
+
+ @SerializedName(ApiConstants.USERNAME)
+ @Param(description = "the admin that annotated this host", since = "4.11")
+ private String username;
// Default visibility to support accessing the details from unit tests
Map getDetails() {
@@ -413,6 +429,14 @@ public void setSuitableForMigration(Boolean suitableForMigration) {
this.suitableForMigration = suitableForMigration;
}
+ public HostHAResponse getHostHAResponse() {
+ return hostHAResponse;
+ }
+
+ public void setHostHAResponse(final HAConfig config) {
+ this.hostHAResponse = new HostHAResponse(config);
+ }
+
public OutOfBandManagementResponse getOutOfBandManagementResponse() {
return outOfBandManagementResponse;
}
@@ -445,6 +469,18 @@ public void setHaHost(Boolean haHost) {
this.haHost = haHost;
}
+ public void setAnnotation(String annotation) {
+ this.annotation = annotation;
+ }
+
+ public void setLastAnnotated(Date lastAnnotated) {
+ this.lastAnnotated = lastAnnotated;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
public void setDetails(Map details) {
if (details == null) {
diff --git a/api/src/org/apache/cloudstack/api/response/LoadBalancerResponse.java b/api/src/org/apache/cloudstack/api/response/LoadBalancerResponse.java
index 21e1dab450e..1eb8fca5087 100644
--- a/api/src/org/apache/cloudstack/api/response/LoadBalancerResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/LoadBalancerResponse.java
@@ -95,6 +95,10 @@
@Param(description = "the id of the zone the rule belongs to")
private String zoneId;
+ @SerializedName(ApiConstants.ZONE_NAME)
+ @Param(description = "the name of the zone the load balancer rule belongs to", since = "4.11")
+ private String zoneName;
+
@SerializedName(ApiConstants.PROTOCOL)
@Param(description = "the protocol of the loadbalanacer rule")
private String lbProtocol;
@@ -166,6 +170,10 @@ public void setZoneId(String zoneId) {
this.zoneId = zoneId;
}
+ public void setZoneName(String zoneName) {
+ this.zoneName = zoneName;
+ }
+
@Override
public void setProjectId(String projectId) {
this.projectId = projectId;
diff --git a/api/src/org/apache/cloudstack/api/response/OutOfBandManagementResponse.java b/api/src/org/apache/cloudstack/api/response/OutOfBandManagementResponse.java
index 19594d29506..c0282c8a823 100644
--- a/api/src/org/apache/cloudstack/api/response/OutOfBandManagementResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/OutOfBandManagementResponse.java
@@ -91,7 +91,7 @@ public OutOfBandManagementResponse(final OutOfBandManagement outOfBandManagement
this.setDriver(outOfBandManagementConfig.getDriver());
this.setIpAddress(outOfBandManagementConfig.getAddress());
if (outOfBandManagementConfig.getPort() != null) {
- this.setPort(String.valueOf(outOfBandManagementConfig.getPort()));
+ this.setPort(outOfBandManagementConfig.getPort());
}
this.setUsername(outOfBandManagementConfig.getUsername());
if (!Strings.isNullOrEmpty(outOfBandManagementConfig.getPassword())) {
diff --git a/api/src/org/apache/cloudstack/api/response/SnapshotResponse.java b/api/src/org/apache/cloudstack/api/response/SnapshotResponse.java
index a49a4e375b2..bb2ff7f6d0e 100644
--- a/api/src/org/apache/cloudstack/api/response/SnapshotResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/SnapshotResponse.java
@@ -112,6 +112,10 @@
@Param(description = "display name of the os on volume")
private String osDisplayName;
+ @SerializedName(ApiConstants.VIRTUAL_SIZE)
+ @Param(description = "virtual size of backedup snapshot on image store")
+ private long virtualSize;
+
@Override
public String getObjectId() {
return this.getId();
@@ -221,4 +225,8 @@ public void setOsTypeId(String osTypeId) {
public void setOsDisplayName(String osDisplayName) {
this.osDisplayName = osDisplayName;
}
+
+ public void setVirtualSize(long virtualSize) {
+ this.virtualSize = virtualSize;
+ }
}
\ No newline at end of file
diff --git a/api/src/org/apache/cloudstack/api/response/SslCertResponse.java b/api/src/org/apache/cloudstack/api/response/SslCertResponse.java
index d722e9845de..aa729f123b4 100644
--- a/api/src/org/apache/cloudstack/api/response/SslCertResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/SslCertResponse.java
@@ -72,6 +72,10 @@
@Param(description = "List of loabalancers this certificate is bound to")
List<String> lbIds;
+ @SerializedName(ApiConstants.NAME)
+ @Param(description = "name")
+ private String name;
+
public SslCertResponse() {
}
@@ -83,6 +87,10 @@ public void setCertificate(String cert) {
this.certificate = cert;
}
+ public void setName(String name) {
+ this.name = name;
+ }
+
public void setAccountName(String accountName) {
this.accountName = accountName;
}
diff --git a/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java b/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java
index b7f7d0b41ee..02d5c44a93a 100644
--- a/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java
@@ -16,18 +16,16 @@
// under the License.
package org.apache.cloudstack.api.response;
-import java.util.Date;
-import java.util.Map;
-
+import com.cloud.serializer.Param;
+import com.cloud.storage.StoragePool;
+import com.cloud.storage.StoragePoolStatus;
import com.google.gson.annotations.SerializedName;
-
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference;
-import com.cloud.serializer.Param;
-import com.cloud.storage.StoragePool;
-import com.cloud.storage.StoragePoolStatus;
+import java.util.Date;
+import java.util.Map;
@EntityReference(value = StoragePool.class)
public class StoragePoolResponse extends BaseResponse {
@@ -119,6 +117,10 @@
@Param(description = "true if this pool is suitable to migrate a volume," + " false otherwise")
private Boolean suitableForMigration;
+ @SerializedName("provider")
+ @Param(description = "Storage provider for this pool")
+ private String provider;
+
@SerializedName(ApiConstants.STORAGE_CAPABILITIES)
@Param(description = "the storage pool capabilities")
private Map<String, String> caps;
@@ -317,4 +319,12 @@ public String getOverProvisionFactor() {
public Boolean getSuitableForMigration() {
return suitableForMigration;
}
+
+ public String getProvider() {
+ return provider;
+ }
+
+ public void setProvider(String provider) {
+ this.provider = provider;
+ }
}
diff --git a/api/src/org/apache/cloudstack/api/response/SystemVmResponse.java b/api/src/org/apache/cloudstack/api/response/SystemVmResponse.java
index 9e20b49dfde..49ab473a37a 100644
--- a/api/src/org/apache/cloudstack/api/response/SystemVmResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/SystemVmResponse.java
@@ -17,6 +17,7 @@
package org.apache.cloudstack.api.response;
import java.util.Date;
+import java.util.List;
import com.google.gson.annotations.SerializedName;
@@ -141,7 +142,13 @@
@Param(description = "the number of active console sessions for the console proxy system vm")
private Integer activeViewerSessions;
- // private Long objectId;
+ @SerializedName("guestvlan")
+ @Param(description = "guest vlan range")
+ private String guestVlan;
+
+ @SerializedName("publicvlan")
+ @Param(description = "public vlan range")
+ private List<String> publicVlan;
@Override
public String getObjectId() {
@@ -355,4 +362,20 @@ public String getLinkLocalNetmask() {
public void setLinkLocalNetmask(String linkLocalNetmask) {
this.linkLocalNetmask = linkLocalNetmask;
}
+
+ public String getGuestVlan() {
+ return guestVlan;
+ }
+
+ public void setGuestVlan(String guestVlan) {
+ this.guestVlan = guestVlan;
+ }
+
+ public List<String> getPublicVlan() {
+ return publicVlan;
+ }
+
+ public void setPublicVlan(List<String> publicVlan) {
+ this.publicVlan = publicVlan;
+ }
}
diff --git a/api/src/org/apache/cloudstack/api/response/TemplateResponse.java b/api/src/org/apache/cloudstack/api/response/TemplateResponse.java
index c576493b8ef..7cbcd1dc9ff 100644
--- a/api/src/org/apache/cloudstack/api/response/TemplateResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/TemplateResponse.java
@@ -117,6 +117,10 @@
@Param(description = "the size of the template")
private Long size;
+ @SerializedName(ApiConstants.PHYSICAL_SIZE)
+ @Param(description = "the physical size of the template")
+ private Long physicalSize;
+
@SerializedName("templatetype")
@Param(description = "the type of the template")
private String templateType;
@@ -275,6 +279,10 @@ public void setSize(Long size) {
this.size = size;
}
+ public void setPhysicalSize(Long physicalSize) {
+ this.physicalSize = physicalSize;
+ }
+
public void setTemplateType(String templateType) {
this.templateType = templateType;
}
diff --git a/api/src/org/apache/cloudstack/api/response/UserResponse.java b/api/src/org/apache/cloudstack/api/response/UserResponse.java
index d96f632f1a3..dd10510c03c 100644
--- a/api/src/org/apache/cloudstack/api/response/UserResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/UserResponse.java
@@ -66,6 +66,10 @@
@Param(description = "the account type of the user")
private Short accountType;
+ @SerializedName("usersource")
+ @Param(description = "the source type of the user in lowercase, such as native, ldap, saml2")
+ private String userSource;
+
@SerializedName(ApiConstants.ROLE_ID)
@Param(description = "the ID of the role")
private String roleId;
@@ -260,4 +264,15 @@ public void setIsCallerChildDomain(boolean isCallerChildDomain) {
public void setIsDefault(Boolean isDefault) {
this.isDefault = isDefault;
}
+
+ public String getUserSource() {
+ return userSource;
+ }
+
+ public void setUserSource(User.Source userSource) {
+ this.userSource = userSource.toString().toLowerCase();
+ if (this.userSource.equals(User.Source.UNKNOWN.toString().toLowerCase())) {
+ this.userSource = User.Source.NATIVE.toString().toLowerCase();
+ }
+ }
}
diff --git a/api/src/org/apache/cloudstack/ca/CAManager.java b/api/src/org/apache/cloudstack/ca/CAManager.java
new file mode 100644
index 00000000000..c32cfbfe345
--- /dev/null
+++ b/api/src/org/apache/cloudstack/ca/CAManager.java
@@ -0,0 +1,163 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ca;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.X509Certificate;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cloudstack.framework.ca.CAProvider;
+import org.apache.cloudstack.framework.ca.CAService;
+import org.apache.cloudstack.framework.ca.Certificate;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.Configurable;
+
+import com.cloud.exception.AgentUnavailableException;
+import com.cloud.exception.OperationTimedoutException;
+import com.cloud.host.Host;
+import com.cloud.utils.component.PluggableService;
+
+public interface CAManager extends CAService, Configurable, PluggableService {
+
+ ConfigKey<String> CAProviderPlugin = new ConfigKey<>("Advanced", String.class,
+ "ca.framework.provider.plugin",
+ "root",
+ "The CA provider plugin that is used for secure CloudStack management server-agent communication for encryption and authentication. Restart management server(s) when changed.", true);
+
+ ConfigKey<Integer> CertKeySize = new ConfigKey<>("Advanced", Integer.class,
+ "ca.framework.cert.keysize",
+ "2048",
+ "The key size to be used for random certificate keypair generation.", true);
+
+ ConfigKey<String> CertSignatureAlgorithm = new ConfigKey<>("Advanced", String.class,
+ "ca.framework.cert.signature.algorithm",
+ "SHA256withRSA",
+ "The default signature algorithm to use for certificate generation.", true);
+
+
+ ConfigKey<Integer> CertValidityPeriod = new ConfigKey<>("Advanced", Integer.class,
+ "ca.framework.cert.validity.period",
+ "365",
+ "The validity period of a client certificate in number of days. Set the value to be more than the expiry alert period.", true);
+
+ ConfigKey<Boolean> AutomaticCertRenewal = new ConfigKey<>("Advanced", Boolean.class,
+ "ca.framework.cert.automatic.renewal",
+ "true",
+ "Enable automatic renewal and provisioning of certificate to agents as supported by the configured CA plugin.", true, ConfigKey.Scope.Cluster);
+
+ ConfigKey<Long> CABackgroundJobDelay = new ConfigKey<>("Advanced", Long.class,
+ "ca.framework.background.task.delay",
+ "3600",
+ "The CA framework background task delay in seconds. Background task runs expiry checks and renews certificate if auto-renewal is enabled.", true);
+
+ ConfigKey<Integer> CertExpiryAlertPeriod = new ConfigKey<>("Advanced", Integer.class,
+ "ca.framework.cert.expiry.alert.period",
+ "15",
+ "The number of days before expiry of a client certificate, the validations are checked. Admins are alerted when auto-renewal is not allowed, otherwise auto-renewal is attempted.", true, ConfigKey.Scope.Cluster);
+
+ /**
+ * Returns a list of available CA provider plugins
+ * @return returns list of CAProvider
+ */
+ List<CAProvider> getCaProviders();
+
+ /**
+ * Returns a map of active agents/hosts certificates
+ * @return returns a non-null map
+ */
+ Map<String, X509Certificate> getActiveCertificatesMap();
+
+ /**
+ * Checks whether the configured CA plugin can provision/create certificates
+ * @return returns certificate creation capability
+ */
+ boolean canProvisionCertificates();
+
+ /**
+ * Returns PEM-encoded chained CA certificate
+ * @param caProvider
+ * @return returns CA certificate chain string
+ */
+ String getCaCertificate(final String caProvider) throws IOException;
+
+ /**
+ * Issues client Certificate
+ * @param csr
+ * @param ipAddresses
+ * @param domainNames
+ * @param validityDays
+ * @param provider
+ * @return returns Certificate
+ */
+ Certificate issueCertificate(final String csr, final List<String> domainNames, final List<String> ipAddresses, final Integer validityDays, final String provider);
+
+ /**
+ * Revokes certificate from provided serial and CN
+ * @param certSerial
+ * @param certCn
+ * @return returns success/failure as boolean
+ */
+ boolean revokeCertificate(final BigInteger certSerial, final String certCn, final String provider);
+
+ /**
+ * Provisions certificate for given active and connected agent host
+ * @param host
+ * @param provider
+ * @return returns success/failure as boolean
+ */
+ boolean provisionCertificate(final Host host, final Boolean reconnect, final String provider);
+
+ /**
+ * Setups up a new keystore and generates CSR for a host
+ * @param host
+ * @param sshAccessDetails when provided, VirtualRoutingResource uses router proxy to execute commands via SSH in systemvms
+ * @return
+ * @throws AgentUnavailableException
+ * @throws OperationTimedoutException
+ */
+ String generateKeyStoreAndCsr(final Host host, final Map<String, String> sshAccessDetails) throws AgentUnavailableException, OperationTimedoutException;
+
+ /**
+ * Deploys a Certificate payload to a provided host
+ * @param host
+ * @param certificate
+ * @param reconnect when true the host/agent is reconnected on successful deployment of the certificate
+ * @param sshAccessDetails when provided, VirtualRoutingResource uses router proxy to execute commands via SSH in systemvms
+ * @return
+ * @throws AgentUnavailableException
+ * @throws OperationTimedoutException
+ */
+ boolean deployCertificate(final Host host, final Certificate certificate, final Boolean reconnect, final Map<String, String> sshAccessDetails) throws AgentUnavailableException, OperationTimedoutException;
+
+ /**
+ * Removes the host from an internal active client/certificate map
+ * @param host
+ */
+ void purgeHostCertificate(final Host host);
+
+ /**
+ * Sends a CA cert event alert to admins with a subject and a message
+ * @param host
+ * @param subject
+ * @param message
+ */
+ void sendAlert(final Host host, final String subject, final String message);
+
+}
diff --git a/api/src/org/apache/cloudstack/ha/HAConfig.java b/api/src/org/apache/cloudstack/ha/HAConfig.java
new file mode 100644
index 00000000000..95b5c9bdfd7
--- /dev/null
+++ b/api/src/org/apache/cloudstack/ha/HAConfig.java
@@ -0,0 +1,146 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.ha;
+
+import com.cloud.utils.fsm.StateMachine2;
+import com.cloud.utils.fsm.StateObject;
+import org.apache.cloudstack.api.InternalIdentity;
+import org.apache.cloudstack.utils.identity.ManagementServerNode;
+
+public interface HAConfig extends StateObject<HAConfig.HAState>, InternalIdentity {
+
+ long getResourceId();
+ HAResource.ResourceType getResourceType();
+ boolean isEnabled();
+ HAState getState();
+ String getHaProvider();
+ Long getManagementServerId();
+
+ enum Event {
+ Eligible,
+ Ineligible,
+ Disabled,
+ Enabled,
+ HealthCheckPassed,
+ HealthCheckFailed,
+ PerformActivityCheck,
+ TooFewActivityCheckSamples,
+ PeriodicRecheckResourceActivity,
+ ActivityCheckFailureOverThresholdRatio,
+ ActivityCheckFailureUnderThresholdRatio,
+ PowerCycle,
+ Recovered,
+ RetryRecovery,
+ RecoveryWaitPeriodTimeout,
+ RecoveryOperationThresholdExceeded,
+ RetryFencing,
+ Fenced;
+
+ public Long getServerId() {
+ // TODO: change in future if we've better claim & ownership
+ // Right now the first one to update the db wins
+ // and mgmt server id would eventually become consistent
+ return ManagementServerNode.getManagementServerId();
+ }
+ }
+
+ enum HAState {
+ Disabled("HA Operations disabled"),
+ Available("The resource is healthy"),
+ Ineligible("The current state does not support HA/recovery"),
+ Suspect("Most recent health check failed"),
+ Degraded("The resource cannot be managed, but services end user requests"),
+ Checking("The activity checks are currently being performed"),
+ Recovering("The resource is undergoing recovery operation"),
+ Recovered("The resource is recovered"),
+ Fencing("The resource is undergoing fence operation"),
+ Fenced("The resource is fenced");
+
+ String description;
+
+ HAState(String description) {
+ this.description = description;
+ }
+
+ public static StateMachine2<HAState, Event, HAConfig> getStateMachine() {
+ return FSM;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ private static final StateMachine2<HAState, Event, HAConfig> FSM = new StateMachine2<>();
+
+ static {
+ FSM.addInitialTransition(Event.Disabled, Disabled);
+ FSM.addInitialTransition(Event.Enabled, Available);
+ FSM.addInitialTransition(Event.Ineligible, Ineligible);
+
+ FSM.addTransition(Disabled, Event.Enabled, Available);
+
+ FSM.addTransition(Ineligible, Event.Disabled, Disabled);
+ FSM.addTransition(Ineligible, Event.Ineligible, Ineligible);
+ FSM.addTransition(Ineligible, Event.Eligible, Available);
+
+ FSM.addTransition(Available, Event.Disabled, Disabled);
+ FSM.addTransition(Available, Event.Ineligible, Ineligible);
+ FSM.addTransition(Available, Event.HealthCheckPassed, Available);
+ FSM.addTransition(Available, Event.HealthCheckFailed, Suspect);
+
+ FSM.addTransition(Suspect, Event.Disabled, Disabled);
+ FSM.addTransition(Suspect, Event.Ineligible, Ineligible);
+ FSM.addTransition(Suspect, Event.HealthCheckFailed, Suspect);
+ FSM.addTransition(Suspect, Event.PerformActivityCheck, Checking);
+ FSM.addTransition(Suspect, Event.HealthCheckPassed, Available);
+
+ FSM.addTransition(Checking, Event.Disabled, Disabled);
+ FSM.addTransition(Checking, Event.Ineligible, Ineligible);
+ FSM.addTransition(Checking, Event.TooFewActivityCheckSamples, Suspect);
+ FSM.addTransition(Checking, Event.ActivityCheckFailureUnderThresholdRatio, Degraded);
+ FSM.addTransition(Checking, Event.ActivityCheckFailureOverThresholdRatio, Recovering);
+
+ FSM.addTransition(Degraded, Event.Disabled, Disabled);
+ FSM.addTransition(Degraded, Event.Ineligible, Ineligible);
+ FSM.addTransition(Degraded, Event.HealthCheckFailed, Degraded);
+ FSM.addTransition(Degraded, Event.HealthCheckPassed, Available);
+ FSM.addTransition(Degraded, Event.PeriodicRecheckResourceActivity, Suspect);
+
+ FSM.addTransition(Recovering, Event.Disabled, Disabled);
+ FSM.addTransition(Recovering, Event.Ineligible, Ineligible);
+ FSM.addTransition(Recovering, Event.RetryRecovery, Recovering);
+ FSM.addTransition(Recovering, Event.Recovered, Recovered);
+ FSM.addTransition(Recovering, Event.RecoveryOperationThresholdExceeded, Fencing);
+
+ FSM.addTransition(Recovered, Event.Disabled, Disabled);
+ FSM.addTransition(Recovered, Event.Ineligible, Ineligible);
+ FSM.addTransition(Recovered, Event.RecoveryWaitPeriodTimeout, Available);
+
+ FSM.addTransition(Fencing, Event.Disabled, Disabled);
+ FSM.addTransition(Fencing, Event.Ineligible, Ineligible);
+ FSM.addTransition(Fencing, Event.RetryFencing, Fencing);
+ FSM.addTransition(Fencing, Event.Fenced, Fenced);
+
+ FSM.addTransition(Fenced, Event.Disabled, Disabled);
+ FSM.addTransition(Fenced, Event.HealthCheckPassed, Ineligible);
+ FSM.addTransition(Fenced, Event.HealthCheckFailed, Fenced);
+ }
+ }
+}
diff --git a/api/src/org/apache/cloudstack/ha/HAConfigManager.java b/api/src/org/apache/cloudstack/ha/HAConfigManager.java
new file mode 100644
index 00000000000..c9a20358c36
--- /dev/null
+++ b/api/src/org/apache/cloudstack/ha/HAConfigManager.java
@@ -0,0 +1,96 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ha;
+
+import com.cloud.dc.DataCenter;
+import com.cloud.org.Cluster;
+
+import java.util.List;
+
+/**
+ * @since 4.11
+ */
+public interface HAConfigManager {
+ /**
+ * Configures HA for a resource by accepting the resource type and HA provider
+ * @param resourceId the ID of the resource
+ * @param resourceType the type of the resource
+ * @param haProvider the name of the HA provider
+ */
+ boolean configureHA(Long resourceId, HAResource.ResourceType resourceType, String haProvider);
+
+ /**
+ * Enables HA for resource Id of a specific resource type
+ * @param resourceId the ID of the resource
+ * @param resourceType the type of the resource
+ * @return returns true on successful enable
+ */
+ boolean enableHA(Long resourceId, HAResource.ResourceType resourceType);
+
+ /**
+ * Disables HA for resource Id of a specific resource type
+ * @param resourceId the ID of the resource
+ * @param resourceType the type of the resource
+ * @return returns true on successful disable
+ */
+ boolean disableHA(Long resourceId, HAResource.ResourceType resourceType);
+
+ /**
+ * Enables HA across a cluster
+ * @param cluster the cluster
+ * @return returns operation success
+ */
+ boolean enableHA(final Cluster cluster);
+
+ /**
+ * Disables HA across a cluster
+ * @param cluster the cluster
+ * @return returns operation success
+ */
+ boolean disableHA(final Cluster cluster);
+
+ /**
+ * Enables HA across a zone
+ * @param zone the zone
+ * @return returns operation success
+ */
+ boolean enableHA(final DataCenter zone);
+
+ /**
+ * Disables HA across a zone
+ * @param zone the zone
+ * @return returns operation success
+ */
+ boolean disableHA(final DataCenter zone);
+
+ /**
+ * Returns list of HA config for resources, by resource ID and/or type if provided
+ * @param resourceId (optional) ID of the resource
+ * @param resourceType (optional) type of the resource
+ * @return returns list of ha config for the resource
+ */
+ List<HAConfig> listHAResources(final Long resourceId, final HAResource.ResourceType resourceType);
+
+ /**
+ * Returns list of HA providers for resources
+ * @param resourceType type of the resource
+ * @param entityType sub-type of the resource
+ * @return returns list of ha provider names
+ */
+ List<String> listHAProviders(final HAResource.ResourceType resourceType, final HAResource.ResourceSubType entityType);
+}
diff --git a/api/src/org/apache/cloudstack/ha/HAResource.java b/api/src/org/apache/cloudstack/ha/HAResource.java
new file mode 100644
index 00000000000..650a58b3297
--- /dev/null
+++ b/api/src/org/apache/cloudstack/ha/HAResource.java
@@ -0,0 +1,37 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ha;
+
+import org.apache.cloudstack.kernel.Partition;
+
+public interface HAResource extends Partition {
+ enum ResourceType {
+ Host,
+ VirtualMachine
+ }
+
+ enum ResourceSubType {
+ KVM,
+ Simulator,
+ Unknown
+ }
+
+ long getDataCenterId();
+ Long getClusterId();
+ ResourceType resourceType();
+}
diff --git a/api/src/org/apache/cloudstack/kernel/Partition.java b/api/src/org/apache/cloudstack/kernel/Partition.java
new file mode 100644
index 00000000000..6d93e3e23ce
--- /dev/null
+++ b/api/src/org/apache/cloudstack/kernel/Partition.java
@@ -0,0 +1,28 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.kernel;
+
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.api.InternalIdentity;
+
+public interface Partition extends InternalIdentity, Identity {
+ enum PartitionType {
+ Zone, Pod, Cluster, Host, VM
+ }
+ PartitionType partitionType();
+}
diff --git a/api/src/org/apache/cloudstack/network/tls/SslCert.java b/api/src/org/apache/cloudstack/network/tls/SslCert.java
index fb1590c539a..074bba6c111 100644
--- a/api/src/org/apache/cloudstack/network/tls/SslCert.java
+++ b/api/src/org/apache/cloudstack/network/tls/SslCert.java
@@ -31,5 +31,5 @@
public String getPassword();
public String getFingerPrint();
-
+ public String getName();
}
diff --git a/api/src/org/apache/cloudstack/outofbandmanagement/OutOfBandManagement.java b/api/src/org/apache/cloudstack/outofbandmanagement/OutOfBandManagement.java
index 1a22328e02e..972d6261674 100644
--- a/api/src/org/apache/cloudstack/outofbandmanagement/OutOfBandManagement.java
+++ b/api/src/org/apache/cloudstack/outofbandmanagement/OutOfBandManagement.java
@@ -39,7 +39,7 @@
String getAddress();
- Integer getPort();
+ String getPort();
String getUsername();
@@ -53,7 +53,7 @@
void setAddress(String address);
- void setPort(Integer port);
+ void setPort(String port);
void setUsername(String username);
diff --git a/api/src/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementService.java b/api/src/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementService.java
index 699b2c6a99b..a8b73b73889 100644
--- a/api/src/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementService.java
+++ b/api/src/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementService.java
@@ -30,9 +30,6 @@
ConfigKey<Long> ActionTimeout = new ConfigKey<Long>("Advanced", Long.class, "outofbandmanagement.action.timeout", "60",
"The out of band management action timeout in seconds, configurable by cluster", true, ConfigKey.Scope.Cluster);
- ConfigKey<Long> SyncThreadInterval = new ConfigKey<Long>("Advanced", Long.class, "outofbandmanagement.sync.interval", "300000",
- "The interval (in milliseconds) when the out-of-band management background sync are retrieved", true, ConfigKey.Scope.Global);
-
ConfigKey<Integer> SyncThreadPoolSize = new ConfigKey<Integer>("Advanced", Integer.class, "outofbandmanagement.sync.poolsize", "50",
"The out of band management background sync thread pool size", true, ConfigKey.Scope.Global);
@@ -49,7 +46,7 @@
OutOfBandManagementResponse disableOutOfBandManagement(Cluster cluster);
OutOfBandManagementResponse disableOutOfBandManagement(Host host);
- OutOfBandManagementResponse configureOutOfBandManagement(Host host, ImmutableMap<OutOfBandManagement.Option, String> options);
- OutOfBandManagementResponse executeOutOfBandManagementPowerOperation(Host host, OutOfBandManagement.PowerOperation operation, Long timeout);
- OutOfBandManagementResponse changeOutOfBandManagementPassword(Host host, String password);
+ OutOfBandManagementResponse configure(Host host, ImmutableMap<OutOfBandManagement.Option, String> options);
+ OutOfBandManagementResponse executePowerOperation(Host host, OutOfBandManagement.PowerOperation operation, Long timeout);
+ OutOfBandManagementResponse changePassword(Host host, String password);
}
diff --git a/api/src/org/apache/cloudstack/poll/BackgroundPollManager.java b/api/src/org/apache/cloudstack/poll/BackgroundPollManager.java
new file mode 100644
index 00000000000..b9d55000294
--- /dev/null
+++ b/api/src/org/apache/cloudstack/poll/BackgroundPollManager.java
@@ -0,0 +1,30 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.poll;
+
+public interface BackgroundPollManager {
+ /**
+ * Submits a background poll task that need to run continuously in the background
+ * to poll external resources, update states, trigger actions etc.
+ * Tasks must be submitted by a manager in configure-phase, the list of submitted tasks
+ * are then submitted to the internal executor service during start-phase.
+ * @param task periodic background task
+ * @since 4.11
+ */
+ void submitTask(final BackgroundPollTask task);
+}
diff --git a/api/src/org/apache/cloudstack/poll/BackgroundPollTask.java b/api/src/org/apache/cloudstack/poll/BackgroundPollTask.java
new file mode 100644
index 00000000000..5f1b3300c48
--- /dev/null
+++ b/api/src/org/apache/cloudstack/poll/BackgroundPollTask.java
@@ -0,0 +1,27 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.poll;
+
+public interface BackgroundPollTask extends Runnable {
+ /**
+ * Returns delay in milliseconds between two rounds
+ * When it returns null a default value is used
+ * @return
+ */
+ Long getDelay();
+}
diff --git a/api/test/com/cloud/network/IsolationMethodTest.java b/api/test/com/cloud/network/IsolationMethodTest.java
new file mode 100644
index 00000000000..2db3ec55db2
--- /dev/null
+++ b/api/test/com/cloud/network/IsolationMethodTest.java
@@ -0,0 +1,89 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.network;
+
+import org.junit.After;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+public class IsolationMethodTest {
+ @After
+ public void cleanTheRegistry() {
+ PhysicalNetwork.IsolationMethod.registeredIsolationMethods.removeAll(PhysicalNetwork.IsolationMethod.registeredIsolationMethods);
+ }
+
+ @Test
+ public void equalsTest() throws Exception {
+ PhysicalNetwork.IsolationMethod method = new PhysicalNetwork.IsolationMethod("bla");
+ assertEquals(PhysicalNetwork.IsolationMethod.UNKNOWN_PROVIDER, method.provider);
+ assertEquals(new PhysicalNetwork.IsolationMethod("bla", PhysicalNetwork.IsolationMethod.UNKNOWN_PROVIDER), method);
+ }
+
+ @Test
+ public void toStringTest() throws Exception {
+ PhysicalNetwork.IsolationMethod method = new PhysicalNetwork.IsolationMethod("bla", "blob");
+ assertEquals("bla", method.toString());
+
+ }
+
+ @Test
+ public void getGeneric() throws Exception {
+ PhysicalNetwork.IsolationMethod method = new PhysicalNetwork.IsolationMethod("bla", "blob");
+ method = new PhysicalNetwork.IsolationMethod("bla");
+
+ assertEquals("blob",PhysicalNetwork.IsolationMethod.getIsolationMethod("bla").getProvider());
+ }
+
+ @Test
+ public void removeUnregistered() throws Exception {
+ assertFalse(PhysicalNetwork.IsolationMethod.remove("bla", "blob"));
+ }
+
+ @Test
+ public void removeSuccesfulGeneric() throws Exception {
+ PhysicalNetwork.IsolationMethod method = new PhysicalNetwork.IsolationMethod("bla", "blob");
+ method = new PhysicalNetwork.IsolationMethod("bla");
+
+ PhysicalNetwork.IsolationMethod.remove("bla", "blob");
+ assertEquals(PhysicalNetwork.IsolationMethod.UNKNOWN_PROVIDER,PhysicalNetwork.IsolationMethod.getIsolationMethod("bla").getProvider());
+ }
+
+ @Test(expected= PhysicalNetwork.IsolationMethod.IsolationMethodNotRegistered.class)
+ public void removeSuccesfulSpecificByString() throws Exception {
+ PhysicalNetwork.IsolationMethod method = new PhysicalNetwork.IsolationMethod("bla", "blob");
+
+ PhysicalNetwork.IsolationMethod.remove("bla", "blob");
+ PhysicalNetwork.IsolationMethod.getIsolationMethod("bla");
+ }
+
+ @Test(expected= PhysicalNetwork.IsolationMethod.IsolationMethodNotRegistered.class)
+ public void removeSuccesfulSpecificObject() throws Exception {
+ PhysicalNetwork.IsolationMethod method = new PhysicalNetwork.IsolationMethod("bla");
+
+ PhysicalNetwork.IsolationMethod.remove(method);
+ PhysicalNetwork.IsolationMethod.getIsolationMethod("bla");
+ }
+
+ @Test
+ public void getIsolationMethodTest() throws Exception {
+ PhysicalNetwork.IsolationMethod method = new PhysicalNetwork.IsolationMethod("bla");
+ final PhysicalNetwork.IsolationMethod isolationMethod = PhysicalNetwork.IsolationMethod.getIsolationMethod("bla");
+ assertEquals(method, isolationMethod);
+ }
+}
diff --git a/api/test/com/cloud/network/NetworksTest.java b/api/test/com/cloud/network/NetworksTest.java
index c9102d3a02a..ef582924342 100644
--- a/api/test/com/cloud/network/NetworksTest.java
+++ b/api/test/com/cloud/network/NetworksTest.java
@@ -16,16 +16,16 @@
// under the License.
package com.cloud.network;
-import java.net.URISyntaxException;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
import com.cloud.dc.Vlan;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.IsolationType;
import com.cloud.utils.exception.CloudRuntimeException;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.net.URI;
+import java.net.URISyntaxException;
/**
* @author dhoogland
@@ -43,6 +43,13 @@ public void emptyBroadcastDomainTypeTest() throws URISyntaxException {
Assert.assertEquals("an empty uri should mean a broadcasttype of undecided", BroadcastDomainType.UnDecided, type);
}
+ @Test
+ public void vlanCommaSeparatedTest() throws URISyntaxException {
+ Assert.assertEquals(BroadcastDomainType.getValue(new URI("vlan://100")), "100");
+ Assert.assertEquals(BroadcastDomainType.getValue(new URI("vlan://100-200")), "100-200");
+ Assert.assertEquals(BroadcastDomainType.getValue(new URI("vlan://10-50,12,11,112-170")), "10-50,12,11,112-170");
+ }
+
@Test
public void vlanBroadcastDomainTypeTest() throws URISyntaxException {
String uri1 = "vlan://1";
diff --git a/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreDao.java b/api/test/org/apache/cloudstack/api/command/admin/annotation/AddAnnotationCmdTest.java
similarity index 56%
rename from engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreDao.java
rename to api/test/org/apache/cloudstack/api/command/admin/annotation/AddAnnotationCmdTest.java
index 1827edfe861..06656868994 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreDao.java
+++ b/api/test/org/apache/cloudstack/api/command/admin/annotation/AddAnnotationCmdTest.java
@@ -16,16 +16,25 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.cloudstack.storage.volume.db;
+package org.apache.cloudstack.api.command.admin.annotation;
-import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.MockitoAnnotations;
-import com.cloud.utils.db.GenericDao;
-import com.cloud.utils.fsm.StateDao;
+public class AddAnnotationCmdTest {
-public interface TemplatePrimaryDataStoreDao extends GenericDao<TemplatePrimaryDataStoreVO, Long>,
- StateDao<ObjectInDataStoreStateMachine.State, ObjectInDataStoreStateMachine.Event, TemplatePrimaryDataStoreVO> {
- public TemplatePrimaryDataStoreVO findByTemplateIdAndPoolId(long templateId, long poolId);
+ private AddAnnotationCmd addAnnotationCmd = new AddAnnotationCmd();
- public TemplatePrimaryDataStoreVO findByTemplateIdAndPoolIdAndReady(long templateId, long poolId);
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test (expected = IllegalStateException.class)
+ public void wrongEntityType() throws Exception {
+ addAnnotationCmd.setEntityType("BLA");
+ addAnnotationCmd.setEntityUuid("1");
+ addAnnotationCmd.execute();
+ }
}
diff --git a/api/test/org/apache/cloudstack/api/command/test/CreateSnapshotCmdTest.java b/api/test/org/apache/cloudstack/api/command/test/CreateSnapshotCmdTest.java
index 5e2b2228fab..bc2beb6cb66 100644
--- a/api/test/org/apache/cloudstack/api/command/test/CreateSnapshotCmdTest.java
+++ b/api/test/org/apache/cloudstack/api/command/test/CreateSnapshotCmdTest.java
@@ -82,7 +82,7 @@ public void testCreateSuccess() {
try {
Mockito.when(volumeApiService.takeSnapshot(anyLong(), anyLong(), anyLong(),
- any(Account.class), anyBoolean(), isNull(Snapshot.LocationType.class))).thenReturn(snapshot);
+ any(Account.class), anyBoolean(), isNull(Snapshot.LocationType.class), anyBoolean())).thenReturn(snapshot);
} catch (Exception e) {
Assert.fail("Received exception when success expected " + e.getMessage());
@@ -115,7 +115,7 @@ public void testCreateFailure() {
try {
Mockito.when(volumeApiService.takeSnapshot(anyLong(), anyLong(), anyLong(),
- any(Account.class), anyBoolean(), isNull(Snapshot.LocationType.class))).thenReturn(null);
+ any(Account.class), anyBoolean(), isNull(Snapshot.LocationType.class), anyBoolean())).thenReturn(null);
} catch (Exception e) {
Assert.fail("Received exception when success expected " + e.getMessage());
}
diff --git a/build/replace.properties b/build/replace.properties
index 9e0b65c6901..3d9a4597060 100644
--- a/build/replace.properties
+++ b/build/replace.properties
@@ -27,4 +27,4 @@ AGENTLOG=logs/agent.log
MSMNTDIR=/mnt
COMPONENTS-SPEC=components.xml
REMOTEHOST=localhost
-COMMONLIBDIR=client/target/cloud-client-ui-4.7.0/WEB-INF/lib/
+COMMONLIBDIR=client/target/common/
diff --git a/client/WEB-INF/web.xml b/client/WEB-INF/web.xml
index 73a755b501f..03f7d15db62 100644
--- a/client/WEB-INF/web.xml
+++ b/client/WEB-INF/web.xml
@@ -19,23 +19,20 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
-
- <context-param>
- <param-name>log4jConfigLocation</param-name>
- <param-value>classpath:log4j-cloud.xml</param-value>
- </context-param>
- <listener>
- <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
- </listener>
-
- <listener>
- <listener-class>org.apache.cloudstack.spring.module.web.CloudStackContextLoaderListener</listener-class>
- </listener>
+
<context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>classpath:META-INF/cloudstack/webApplicationContext.xml</param-value>
+ <param-name>log4jConfigLocation</param-name>
+ <param-value>classpath:log4j-cloud.xml</param-value>
</context-param>
-
+
+ <listener>
+ <listener-class>org.apache.cloudstack.spring.module.web.CloudStackContextLoaderListener</listener-class>
+ </listener>
+ <context-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>classpath:META-INF/cloudstack/webApplicationContext.xml</param-value>
+ </context-param>
+
<servlet>
<servlet-name>cloudStartupServlet</servlet-name>
<servlet-class>com.cloud.servlet.CloudStartupServlet</servlet-class>
@@ -47,40 +44,26 @@
<servlet-class>com.cloud.api.ApiServlet</servlet-class>
<load-on-startup>5</load-on-startup>
</servlet>
-
+
<servlet>
<servlet-name>consoleServlet</servlet-name>
<servlet-class>com.cloud.servlet.ConsoleProxyServlet</servlet-class>
<load-on-startup>6</load-on-startup>
</servlet>
-
- <servlet>
- <servlet-name>staticResources</servlet-name>
- <servlet-class>com.cloud.servlet.StaticResourceServlet</servlet-class>
- </servlet>
-
<servlet-mapping>
<servlet-name>apiServlet</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
-
- <servlet-mapping>
- <servlet-name>consoleServlet</servlet-name>
- <url-pattern>/console</url-pattern>
- </servlet-mapping>
-
<servlet-mapping>
- <servlet-name>staticResources</servlet-name>
- <url-pattern>*.css</url-pattern>
- <url-pattern>*.html</url-pattern>
- <url-pattern>*.js</url-pattern>
+ <servlet-name>consoleServlet</servlet-name>
+ <url-pattern>/console</url-pattern>
</servlet-mapping>
<error-page>
- <exception-type>java.lang.Exception</exception-type>
- <location>/error.html</location>
+ <exception-type>java.lang.Exception</exception-type>
+ <location>/error.html</location>
</error-page>
</web-app>
diff --git a/client/bindir/cloud-setup-management.in b/client/bindir/cloud-setup-management.in
index de76007fc80..94a08cb1e1f 100755
--- a/client/bindir/cloud-setup-management.in
+++ b/client/bindir/cloud-setup-management.in
@@ -29,13 +29,13 @@ if __name__ == '__main__':
parser = OptionParser()
parser.add_option("--https", action="store_true", dest="https", help="Enable HTTPs connection of management server")
- parser.add_option("--tomcat7", action="store_true", dest="tomcat7", help="Use Tomcat7 configuration files in Management Server")
+ parser.add_option("--tomcat7", action="store_true", dest="tomcat7", help="Depreciated option, don't use it")
parser.add_option("--no-start", action="store_true", dest="nostart", help="Do not start management server after successful configuration")
(options, args) = parser.parse_args()
if options.https:
glbEnv.svrMode = "HttpsServer"
if options.tomcat7:
- glbEnv.svrConf = "Tomcat7"
+ print "The --tomcat7 option is deprecated, CloudStack now uses embedded Jetty server."
if options.nostart:
glbEnv.noStart = True
diff --git a/client/tomcatconf/commons-logging.properties.in b/client/conf/commons-logging.properties.in
similarity index 97%
rename from client/tomcatconf/commons-logging.properties.in
rename to client/conf/commons-logging.properties.in
index 1e570d65f3b..febd7ba23ae 100644
--- a/client/tomcatconf/commons-logging.properties.in
+++ b/client/conf/commons-logging.properties.in
@@ -17,9 +17,9 @@
# under the License.
#
-# This is the logging properties that goes to the war, there are two logging conf kept at the
+# This is the logging properties that goes to the war, there are two logging conf kept at the
# svn, one for developement (one at src/test-resources) and other for producation
-
+
# Uncomment the next line to disable all logging.
#org.apache.commons.logging.Log=org.apache.commons.logging.impl.NoOpLog
diff --git a/client/tomcatconf/db.properties.in b/client/conf/db.properties.in
similarity index 97%
rename from client/tomcatconf/db.properties.in
rename to client/conf/db.properties.in
index ab7d7c90c16..2f1dcf0d6b8 100644
--- a/client/tomcatconf/db.properties.in
+++ b/client/conf/db.properties.in
@@ -5,9 +5,9 @@
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
-#
+#
# http://www.apache.org/licenses/LICENSE-2.0
-#
+#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -16,7 +16,7 @@
# under the License.
# management server clustering parameters, change cluster.node.IP to the machine IP address
-# in which the management server(Tomcat) is running
+# in which the management server is running
cluster.node.IP=127.0.0.1
cluster.servlet.port=9090
region.id=1
@@ -47,7 +47,6 @@ db.cloud.keyStore=
db.cloud.keyStorePassword=
db.cloud.trustStore=
db.cloud.trustStorePassword=
-db.cloud.keyStorePassphrase=vmops.com
# Encryption Settings
db.cloud.encryption.type=none
diff --git a/client/tomcatconf/ehcache.xml.in b/client/conf/ehcache.xml.in
similarity index 98%
rename from client/tomcatconf/ehcache.xml.in
rename to client/conf/ehcache.xml.in
index 9443d48b83b..19bfd0f6967 100755
--- a/client/tomcatconf/ehcache.xml.in
+++ b/client/conf/ehcache.xml.in
@@ -23,7 +23,7 @@ under the License.
CacheManager Configuration
==========================
An ehcache.xml corresponds to a single CacheManager.
-
+
See instructions below or the ehcache schema (ehcache.xsd) on how to configure.
System property tokens can be specified in this file which are replaced when the configuration is loaded.
@@ -143,7 +143,7 @@ under the License.
The hostname is the hostname of the remote CacheManager peer. The port is the listening
port of the RMICacheManagerPeerListener of the remote CacheManager peer.
-
+
Configuring JGroups replication:
<cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProviderFactory"
properties="connect=UDP(mcast_addr=231.12.21.132;mcast_port=45566;ip_ttl=32;
@@ -160,7 +160,7 @@ under the License.
/>
The only property necessay is the connect String used by jgroups to configure itself. Refer to the Jgroups documentation for explanation
of all the protocols. The example above uses UDP multicast. If the connect property is not specified the default JGroups connection will be
- used.
+ used.
-->
<cacheManagerPeerProviderFactory
@@ -266,7 +266,7 @@ under the License.
to this area and then asynchronously written to disk. The default size is 30MB.
Each spool buffer is used only by its cache. If you get OutOfMemory errors consider
lowering this value. To improve DiskStore performance consider increasing it. Trace level
- logging in the DiskStore will show if put back ups are occurring.
+ logging in the DiskStore will show if put back ups are occurring.
memoryStoreEvictionPolicy:
Policy would be enforced upon reaching the maxElementsInMemory limit. Default
@@ -332,9 +332,9 @@ under the License.
For the Jgroups replication this is done with:
<cacheEventListenerFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"
properties="replicateAsynchronously=true, replicatePuts=true,
- replicateUpdates=true, replicateUpdatesViaCopy=false,
- replicateRemovals=true,asynchronousReplicationIntervalMillis=1000"/>
- This listener supports the same property than the RMICacheReplicationFactory.
+ replicateUpdates=true, replicateUpdatesViaCopy=false,
+ replicateRemovals=true,asynchronousReplicationIntervalMillis=1000"/>
+ This listener supports the same property than the RMICacheReplicationFactory.
Cluster Bootstrapping
@@ -435,7 +435,7 @@ under the License.
disk cache, which in this configuration will go to wherever java.io.tmp is
defined on your system. On a standard Linux system this will be /tmp"
-->
- <!--
+ <!--
<cache name="sampleCache1"
maxElementsInMemory="10000"
maxElementsOnDisk="1000"
@@ -455,7 +455,7 @@ under the License.
is also the maximum cache size. Note that when a cache is eternal, timeToLive and
timeToIdle are not used and do not need to be specified.
-->
- <!--
+ <!--
<cache name="sampleCache2"
maxElementsInMemory="1000"
eternal="true"
@@ -470,7 +470,7 @@ under the License.
persistent between cache and VM restarts. The disk expiry thread interval is set to 10
minutes, overriding the default of 2 minutes.
-->
- <!--
+ <!--
<cache name="sampleCache3"
maxElementsInMemory="500"
eternal="false"
@@ -489,7 +489,7 @@ under the License.
This cache replicates using defaults.
It also bootstraps from the cluster, using default properties.
-->
- <!--
+ <!--
<cache name="sampleDistributedCache1"
maxElementsInMemory="10"
eternal="false"
@@ -509,7 +509,7 @@ under the License.
This cache replicates using specific properties.
It only replicates updates and does so synchronously via copy
-->
- <!--
+ <!--
<cache name="sampleDistributedCache2"
maxElementsInMemory="10"
eternal="false"
@@ -529,7 +529,7 @@ under the License.
This cache replicates using defaults except that the asynchronous replication
interval is set to 200ms.
-->
- <!--
+ <!--
<cache name="sampleDistributedCache3"
maxElementsInMemory="10"
eternal="false"
diff --git a/client/tomcatconf/environment.properties.in b/client/conf/environment.properties.in
similarity index 99%
rename from client/tomcatconf/environment.properties.in
rename to client/conf/environment.properties.in
index f2956cc4abb..e6e6dbd8700 100644
--- a/client/tomcatconf/environment.properties.in
+++ b/client/conf/environment.properties.in
@@ -5,9 +5,9 @@
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
-#
+#
# http://www.apache.org/licenses/LICENSE-2.0
-#
+#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
diff --git a/client/tomcatconf/java.security.ciphers.in b/client/conf/java.security.ciphers.in
similarity index 100%
rename from client/tomcatconf/java.security.ciphers.in
rename to client/conf/java.security.ciphers.in
diff --git a/client/tomcatconf/log4j-cloud.xml.in b/client/conf/log4j-cloud.xml.in
similarity index 99%
rename from client/tomcatconf/log4j-cloud.xml.in
rename to client/conf/log4j-cloud.xml.in
index 125b00204ab..223692881de 100755
--- a/client/tomcatconf/log4j-cloud.xml.in
+++ b/client/conf/log4j-cloud.xml.in
@@ -38,7 +38,7 @@ under the License.
<param name="ConversionPattern" value="%d{ISO8601} %-5p [%c{1.}] (%t:%x) (logid:%X{logcontextid}) %m%n"/>
</layout>
</appender>
-
+
<appender name="APISERVER" class="org.apache.log4j.rolling.RollingFileAppender">
<param name="Append" value="true"/>
<param name="Threshold" value="DEBUG"/>
@@ -111,11 +111,11 @@ under the License.
<category name="com.cloud">
<priority value="DEBUG"/>
</category>
-
+
<category name="org.apache.cloudstack">
<priority value="DEBUG"/>
</category>
-
+
<category name="org.apache.cloudstack">
<priority value="DEBUG"/>
</category>
@@ -123,7 +123,7 @@ under the License.
<category name="com.cloud.utils.nio">
<priority value="INFO"/>
</category>
-
+
<!-- Limit the org.apache category to INFO as its DEBUG is verbose -->
<category name="org.apache">
<priority value="INFO"/>
@@ -136,19 +136,19 @@ under the License.
<category name="org.apache.cloudstack.api.command">
<priority value="TRACE"/>
</category>
-
+
<category name="org">
<priority value="INFO"/>
</category>
-
+
<category name="org.springframework">
<priority value="WARN"/>
</category>
-
+
<category name="org.apache.cloudstack.spring.module.context.ResourceApplicationContext">
<priority value="WARN"/>
</category>
-
+
<category name="net">
<priority value="INFO"/>
</category>
diff --git a/client/conf/server.properties.in b/client/conf/server.properties.in
new file mode 100644
index 00000000000..7140bd26e26
--- /dev/null
+++ b/client/conf/server.properties.in
@@ -0,0 +1,41 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# The binding interface for the management server
+bind.interface=::
+
+# The service context path where URL requests should be served
+context.path=/client
+
+# The HTTP port to be used by the management server
+http.port=8080
+
+# Options to configure and enable HTTPS on management server
+#
+# For management server to pickup these configuration settings, the configured
+# keystore file should exists and be readable by the management server.
+https.enable=false
+https.port=8443
+# The keystore and manager passwords are assumed to be same.
+https.keystore=/etc/cloudstack/management/cloud.jks
+https.keystore.password=vmops.com
+
+# The path to webapp directory
+webapp.dir=/usr/share/cloudstack-management/webapp
+
+# The path to access log file
+access.log=/var/log/cloudstack/management/access.log
diff --git a/client/distro/centos/SYSCONFDIR/rc.d/init.d/cloud-management.in b/client/distro/centos/SYSCONFDIR/rc.d/init.d/cloud-management.in
deleted file mode 100755
index 03a9301f6c7..00000000000
--- a/client/distro/centos/SYSCONFDIR/rc.d/init.d/cloud-management.in
+++ /dev/null
@@ -1,107 +0,0 @@
-#!/bin/bash
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-# @PACKAGE@-management This shell script takes care of starting and stopping Tomcat
-#
-# chkconfig: - 80 20
-#
-### BEGIN INIT INFO
-# Provides: tomcat6
-# Required-Start: $network $syslog
-# Required-Stop: $network $syslog
-# Default-Start:
-# Default-Stop:
-# Description: Release implementation for Servlet 2.5 and JSP 2.1
-# Short-Description: start and stop tomcat
-### END INIT INFO
-#
-# - originally written by Henri Gomez, Keith Irwin, and Nicolas Mailhot
-# - heavily rewritten by Deepak Bhole and Jason Corley
-#
-
-if [ -r /etc/rc.d/init.d/functions ]; then
- . /etc/rc.d/init.d/functions
-fi
-if [ -r /lib/lsb/init-functions ]; then
- . /lib/lsb/init-functions
-fi
-
-
-NAME="$(basename $0)"
-stop() {
- SHUTDOWN_WAIT="40"
- count="0"
- if [ -f /var/run/cloud-management.pid ]; then
- pid=`cat /var/run/cloud-management.pid`
- kill $pid &>/dev/null
- until [ "$(ps --pid $pid | grep -c $pid)" -eq "0" ] || \
- [ "$count" -gt "$SHUTDOWN_WAIT" ]
- do
- sleep 1
- let count="${count}+1"
- done
- if [ "$(ps --pid $pid | grep -c $pid)" -eq "0" ]; then
- log_success_msg "Stopping cloud-management:"
- else
- log_failure_msg "Stopping cloud-management:"
- fi
- else
- echo "Cannot find PID file of Cloud-management"
- log_failure_msg "Stopping cloud-management:"
- fi
-}
-
-set_ulimit() {
- fd_limit=`ulimit -n`
- if [ "$fd_limit" != "4096" ]; then
- user=`whoami`
- if [ $user == "root" ]; then
- ulimit -n 4096
- fi
- fi
-}
-
-handle_pid_file() {
- if [ "$1" -ne 0 ] ; then
- echo "The pid file locates at /var/run/cloud-management.pid and lock file at /var/lock/subsys/cloud-management.
- Starting cloud-management will take care of them or you can manually clean up."
- fi
-}
-
-# See how we were called.
-case "$1" in
- status)
- status ${NAME}
- RETVAL=$?
- handle_pid_file $RETVAL
- ;;
- stop)
- stop
- ;;
- restart)
- stop
- set start
- set_ulimit
- . /etc/rc.d/init.d/tomcat6
- ;;
- *)
- set_ulimit
- . /etc/rc.d/init.d/tomcat6
-esac
-
-exit $RETVAL
diff --git a/client/distro/centos/SYSCONFDIR/sysconfig/cloud-management.in b/client/distro/centos/SYSCONFDIR/sysconfig/cloud-management.in
deleted file mode 100644
index d22a6d5adc2..00000000000
--- a/client/distro/centos/SYSCONFDIR/sysconfig/cloud-management.in
+++ /dev/null
@@ -1,23 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# This file is loaded in /etc/init.d/vmopsmanagement
-# ATM we only do two things here:
-
-dummy=1 ; export TOMCAT_CFG=@MSCONF@/tomcat6.conf ; . @MSCONF@/tomcat6.conf
-#--------------------------
-
diff --git a/client/distro/fedora/SYSCONFDIR/rc.d/init.d/cloud-management.in b/client/distro/fedora/SYSCONFDIR/rc.d/init.d/cloud-management.in
deleted file mode 100755
index bbc46932738..00000000000
--- a/client/distro/fedora/SYSCONFDIR/rc.d/init.d/cloud-management.in
+++ /dev/null
@@ -1,106 +0,0 @@
-#!/bin/bash
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-# @PACKAGE@-management This shell script takes care of starting and stopping Tomcat
-#
-# chkconfig: - 80 20
-#
-### BEGIN INIT INFO
-# Provides: tomcat6
-# Required-Start: $network $syslog
-# Required-Stop: $network $syslog
-# Default-Start:
-# Default-Stop:
-# Description: Release implementation for Servlet 2.5 and JSP 2.1
-# Short-Description: start and stop tomcat
-### END INIT INFO
-#
-# - originally written by Henri Gomez, Keith Irwin, and Nicolas Mailhot
-# - heavily rewritten by Deepak Bhole and Jason Corley
-#
-
-if [ -r /etc/rc.d/init.d/functions ]; then
- . /etc/rc.d/init.d/functions
-fi
-if [ -r /lib/lsb/init-functions ]; then
- . /lib/lsb/init-functions
-fi
-
-set_ulimit() {
- fd_limit=`ulimit -n`
- if [ "$fd_limit" != "4096" ]; then
- user=`whoami`
- if [ $user == "root" ]; then
- ulimit -n 4096
- fi
- fi
-}
-
-NAME="$(basename $0)"
-stop() {
- SHUTDOWN_WAIT="30"
- count="0"
- if [ -f /var/run/cloud-management.pid ]; then
- pid=`cat /var/run/cloud-management.pid`
- kill $pid &>/dev/null
- until [ "$(ps --pid $pid | grep -c $pid)" -eq "0" ] || \
- [ "$count" -gt "$SHUTDOWN_WAIT" ]
- do
- sleep 1
- let count="${count}+1"
- done
- if [ "$(ps --pid $pid | grep -c $pid)" -eq "0" ]; then
- log_success_msg "Stopping cloud-management:"
- else
- log_failure_msg "Stopping cloud-management:"
- fi
- else
- echo "Cannot find PID file of Cloud-management"
- log_failure_msg "Stopping cloud-management:"
- fi
-}
-
-handle_pid_file() {
- if [ "$1" -ne 0 ] ; then
- echo "The pid file locates at /var/run/cloud-management.pid and lock file at /var/lock/subsys/cloud-management.
- Starting cloud-management will take care of them or you can manually clean up."
- fi
-}
-
-# See how we were called.
-case "$1" in
- status)
- status ${NAME}
- RETVAL=$?
- handle_pid_file $RETVAL
- ;;
- stop)
- stop
- ;;
- restart)
- stop
- set start
- set_ulimit
- . /etc/rc.d/init.d/tomcat6
- ;;
- *)
- set_ulimit
- . /etc/rc.d/init.d/tomcat6
-esac
-
-exit $RETVAL
diff --git a/client/distro/fedora/SYSCONFDIR/sysconfig/cloud-management.in b/client/distro/fedora/SYSCONFDIR/sysconfig/cloud-management.in
deleted file mode 100644
index d22a6d5adc2..00000000000
--- a/client/distro/fedora/SYSCONFDIR/sysconfig/cloud-management.in
+++ /dev/null
@@ -1,23 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# This file is loaded in /etc/init.d/vmopsmanagement
-# ATM we only do two things here:
-
-dummy=1 ; export TOMCAT_CFG=@MSCONF@/tomcat6.conf ; . @MSCONF@/tomcat6.conf
-#--------------------------
-
diff --git a/client/distro/opensuse/SYSCONFDIR/init.d/cloud-management.in b/client/distro/opensuse/SYSCONFDIR/init.d/cloud-management.in
deleted file mode 100755
index d071b39d2e7..00000000000
--- a/client/distro/opensuse/SYSCONFDIR/init.d/cloud-management.in
+++ /dev/null
@@ -1,239 +0,0 @@
-#!/bin/sh
-#
-# /etc/init.d/tomcat6 -- startup script for the Tomcat 6 servlet engine
-
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-### BEGIN INIT INFO
-# Provides: tomcat-vmops
-# Required-Start: $local_fs $remote_fs $network
-# Required-Stop: $local_fs $remote_fs $network
-# Should-Start: $named
-# Should-Stop: $named
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-# Short-Description: Start Tomcat (CloudStack).
-# Description: Start the Tomcat servlet engine that runs the CloudStack Management Server.
-### END INIT INFO
-
-PATH=/bin:/usr/bin:/sbin:/usr/sbin
-NAME=cloud-management
-DESC="CloudStack-specific Tomcat servlet engine"
-DAEMON=/usr/bin/jsvc
-CATALINA_HOME=@MSENVIRON@
-DEFAULT=@MSCONF@/tomcat6.conf
-JVM_TMP=/tmp/$NAME-temp
-
-if [ `id -u` -ne 0 ]; then
- echo "You need root privileges to run this script"
- exit 1
-fi
-
-# Make sure tomcat is started with system locale
-if [ -r /etc/default/locale ]; then
- . /etc/default/locale
- export LANG
-fi
-
-. /lib/lsb/init-functions
-. /etc/rc.status
-
-
-# The following variables can be overwritten in $DEFAULT
-
-# Run Tomcat 6 as this user ID
-TOMCAT6_USER=tomcat6
-
-# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not
-# defined in $DEFAULT)
-JDK_DIRS="/usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-sun /usr/lib/jvm/java-1.5.0-sun /usr/lib/j2sdk1.5-sun /usr/lib/j2sdk1.5-ibm"
-
-# Look for the right JVM to use
-for jdir in $JDK_DIRS; do
- if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then
- JAVA_HOME="$jdir"
- fi
-done
-export JAVA_HOME
-
-# Directory for per-instance configuration files and webapps
-CATALINA_BASE=@MSENVIRON@
-
-# Use the Java security manager? (yes/no)
-TOMCAT6_SECURITY=no
-
-# Default Java options
-# Set java.awt.headless=true if JAVA_OPTS is not set so the
-# Xalan XSL transformer can work without X11 display on JDK 1.4+
-# It also looks like the default heap size of 64M is not enough for most cases
-# so the maximum heap size is set to 128M
-if [ -z "$JAVA_OPTS" ]; then
- JAVA_OPTS="-Djava.awt.headless=true -Xmx128M"
-fi
-
-# End of variables that can be overwritten in $DEFAULT
-
-# overwrite settings from default file
-if [ -f "$DEFAULT" ]; then
- . "$DEFAULT"
-fi
-
-if [ ! -f "$CATALINA_HOME/bin/bootstrap.jar" ]; then
- log_failure_msg "$NAME is not installed"
- exit 1
-fi
-
-[ -f "$DAEMON" ] || exit 0
-
-POLICY_CACHE="$CATALINA_BASE/work/catalina.policy"
-
-JAVA_OPTS="$JAVA_OPTS -Djava.endorsed.dirs=$CATALINA_HOME/endorsed -Dcatalina.base=$CATALINA_BASE -Dcatalina.home=$CATALINA_HOME -Djava.io.tmpdir=$JVM_TMP"
-
-# Set the JSP compiler if set in the tomcat6.default file
-if [ -n "$JSP_COMPILER" ]; then
- JAVA_OPTS="$JAVA_OPTS -Dbuild.compiler=$JSP_COMPILER"
-fi
-
-if [ "$TOMCAT6_SECURITY" = "yes" ]; then
- JAVA_OPTS="$JAVA_OPTS -Djava.security.manager -Djava.security.policy=$POLICY_CACHE"
-fi
-
-# Set juli LogManager if logging.properties is provided
-if [ -r "$CATALINA_BASE"/conf/logging.properties ]; then
- JAVA_OPTS="$JAVA_OPTS "-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager" "-Djava.util.logging.config.file="$CATALINA_BASE/conf/logging.properties"
-fi
-
-# Define other required variables
-CATALINA_PID="@PIDDIR@/$NAME.pid"
-BOOTSTRAP_CLASS=org.apache.catalina.startup.Bootstrap
-JSVC_CLASSPATH="/usr/share/java/commons-daemon.jar:$CATALINA_HOME/bin/bootstrap.jar"
-JSVC_CLASSPATH=$CLASSPATH:$JSVC_CLASSPATH
-
-# Look for Java Secure Sockets Extension (JSSE) JARs
-if [ -z "${JSSE_HOME}" -a -r "${JAVA_HOME}/jre/lib/jsse.jar" ]; then
- JSSE_HOME="${JAVA_HOME}/jre/"
-fi
-export JSSE_HOME
-
-case "$1" in
- start)
- if [ -z "$JAVA_HOME" ]; then
- log_failure_msg "no JDK found - please set JAVA_HOME"
- exit 1
- fi
-
- if [ ! -d "$CATALINA_BASE/conf" ]; then
- log_failure_msg "invalid CATALINA_BASE: $CATALINA_BASE"
- exit 1
- fi
-
- log_daemon_msg "Starting $DESC" "$NAME"
- if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
- --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
- >/dev/null; then
-
- # Regenerate POLICY_CACHE file
- umask 022
- echo "// AUTO-GENERATED FILE from /etc/tomcat6/policy.d/" \
- > "$POLICY_CACHE"
- echo "" >> "$POLICY_CACHE"
- if ls $CATALINA_BASE/conf/policy.d/*.policy > /dev/null 2>&1 ; then
- cat $CATALINA_BASE/conf/policy.d/*.policy \
- >> "$POLICY_CACHE"
- fi
-
- # Remove / recreate JVM_TMP directory
- rm -rf "$JVM_TMP"
- mkdir "$JVM_TMP" || {
- log_failure_msg "could not create JVM temporary directory"
- exit 1
- }
- chown $TOMCAT6_USER "$JVM_TMP"
- cd "$JVM_TMP"
-
-
- # fix storage issues on nfs mounts
- umask 000
- $DAEMON -user "$TOMCAT6_USER" -cp "$JSVC_CLASSPATH" \
- -outfile SYSLOG -errfile SYSLOG \
- -pidfile "$CATALINA_PID" $JAVA_OPTS "$BOOTSTRAP_CLASS"
-
- sleep 5
- if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
- --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
- >/dev/null; then
- log_end_msg 1
- else
- log_end_msg 0
- fi
- else
- log_progress_msg "(already running)"
- log_end_msg 0
- fi
- ;;
- stop)
- log_daemon_msg "Stopping $DESC" "$NAME"
- if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
- --user "$TOMCAT6_USER" --startas "$JAVA_HOME/bin/java" \
- >/dev/null; then
- log_progress_msg "(not running)"
- else
- $DAEMON -cp "$JSVC_CLASSPATH" -pidfile "$CATALINA_PID" \
- -stop "$BOOTSTRAP_CLASS"
- fi
- rm -rf "$JVM_TMP"
- log_end_msg 0
- ;;
- status)
- if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
- --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
- >/dev/null; then
-
- if [ -f "$CATALINA_PID" ]; then
- log_success_msg "$DESC is not running, but pid file exists."
- exit 1
- else
- log_success_msg "$DESC is not running."
- exit 3
- fi
- else
- log_success_msg "$DESC is running with pid `cat $CATALINA_PID`"
- fi
- ;;
- restart|force-reload)
- if start-stop-daemon --test --stop --pidfile "$CATALINA_PID" \
- --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
- >/dev/null; then
- $0 stop
- sleep 1
- fi
- $0 start
- ;;
- try-restart)
- if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
- --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
- >/dev/null; then
- $0 start
- fi
- ;;
- *)
- log_success_msg "Usage: $0 {start|stop|restart|try-restart|force-reload|status}"
- exit 1
- ;;
-esac
-
-exit 0
diff --git a/client/distro/opensuse/SYSCONFDIR/sysconfig/cloud-management.in b/client/distro/opensuse/SYSCONFDIR/sysconfig/cloud-management.in
deleted file mode 100644
index d22a6d5adc2..00000000000
--- a/client/distro/opensuse/SYSCONFDIR/sysconfig/cloud-management.in
+++ /dev/null
@@ -1,23 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# This file is loaded in /etc/init.d/vmopsmanagement
-# ATM we only do two things here:
-
-dummy=1 ; export TOMCAT_CFG=@MSCONF@/tomcat6.conf ; . @MSCONF@/tomcat6.conf
-#--------------------------
-
diff --git a/client/distro/rhel/SYSCONFDIR/rc.d/init.d/cloud-management.in b/client/distro/rhel/SYSCONFDIR/rc.d/init.d/cloud-management.in
deleted file mode 100644
index b0be89e8186..00000000000
--- a/client/distro/rhel/SYSCONFDIR/rc.d/init.d/cloud-management.in
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/bin/bash
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-# @PACKAGE@-management This shell script takes care of starting and stopping Tomcat
-#
-# chkconfig: - 80 20
-#
-### BEGIN INIT INFO
-# Provides: tomcat6
-# Required-Start: $network $syslog
-# Required-Stop: $network $syslog
-# Default-Start:
-# Default-Stop:
-# Description: Release implementation for Servlet 2.5 and JSP 2.1
-# Short-Description: start and stop tomcat
-### END INIT INFO
-#
-# - originally written by Henri Gomez, Keith Irwin, and Nicolas Mailhot
-# - heavily rewritten by Deepak Bhole and Jason Corley
-#
-
-if [ -r /etc/rc.d/init.d/functions ]; then
- . /etc/rc.d/init.d/functions
-fi
-if [ -r /lib/lsb/init-functions ]; then
- . /lib/lsb/init-functions
-fi
-
-
-NAME="$(basename $0)"
-stop() {
- SHUTDOWN_WAIT="30"
- count="0"
- if [ -f /var/run/cloud-management.pid ]; then
- pid=`cat /var/run/cloud-management.pid`
- kill $pid &>/dev/null
- until [ "$(ps --pid $pid | grep -c $pid)" -eq "0" ] || \
- [ "$count" -gt "$SHUTDOWN_WAIT" ]
- do
- sleep 1
- let count="${count}+1"
- done
- if [ "$(ps --pid $pid | grep -c $pid)" -eq "0" ]; then
- log_success_msg "Stopping cloud-management:"
- else
- log_failure_msg "Stopping cloud-management:"
- fi
- else
- echo "Cannot find PID file of Cloud-management"
- log_failure_msg "Stopping cloud-management:"
- fi
-}
-
-set_ulimit() {
- fd_limit=`ulimit -n`
- if [ "$fd_limit" != "4096" ]; then
- user=`whoami`
- if [ $user == "root" ]; then
- ulimit -n 4096
- fi
- fi
-}
-
-
-handle_pid_file() {
- if [ "$1" -ne 0 ] ; then
- echo "The pid file locates at /var/run/cloud-management.pid and lock file at /var/lock/subsys/cloud-management.
- Starting cloud-management will take care of them or you can manually clean up."
- fi
-}
-
-# See how we were called.
-case "$1" in
- status)
- status ${NAME}
- RETVAL=$?
- handle_pid_file $RETVAL
- ;;
- stop)
- stop
- ;;
- restart)
- stop
- set start
- set_ulimit
- . /etc/rc.d/init.d/tomcat6
- ;;
- *)
- set_ulimit
- . /etc/rc.d/init.d/tomcat6
-esac
-
-exit $RETVAL
diff --git a/client/distro/rhel/SYSCONFDIR/sysconfig/cloud-management.in b/client/distro/rhel/SYSCONFDIR/sysconfig/cloud-management.in
deleted file mode 100644
index d22a6d5adc2..00000000000
--- a/client/distro/rhel/SYSCONFDIR/sysconfig/cloud-management.in
+++ /dev/null
@@ -1,23 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# This file is loaded in /etc/init.d/vmopsmanagement
-# ATM we only do two things here:
-
-dummy=1 ; export TOMCAT_CFG=@MSCONF@/tomcat6.conf ; . @MSCONF@/tomcat6.conf
-#--------------------------
-
diff --git a/client/distro/sles/SYSCONFDIR/init.d/cloud-management.in b/client/distro/sles/SYSCONFDIR/init.d/cloud-management.in
deleted file mode 100755
index d071b39d2e7..00000000000
--- a/client/distro/sles/SYSCONFDIR/init.d/cloud-management.in
+++ /dev/null
@@ -1,239 +0,0 @@
-#!/bin/sh
-#
-# /etc/init.d/tomcat6 -- startup script for the Tomcat 6 servlet engine
-
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-### BEGIN INIT INFO
-# Provides: tomcat-vmops
-# Required-Start: $local_fs $remote_fs $network
-# Required-Stop: $local_fs $remote_fs $network
-# Should-Start: $named
-# Should-Stop: $named
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-# Short-Description: Start Tomcat (CloudStack).
-# Description: Start the Tomcat servlet engine that runs the CloudStack Management Server.
-### END INIT INFO
-
-PATH=/bin:/usr/bin:/sbin:/usr/sbin
-NAME=cloud-management
-DESC="CloudStack-specific Tomcat servlet engine"
-DAEMON=/usr/bin/jsvc
-CATALINA_HOME=@MSENVIRON@
-DEFAULT=@MSCONF@/tomcat6.conf
-JVM_TMP=/tmp/$NAME-temp
-
-if [ `id -u` -ne 0 ]; then
- echo "You need root privileges to run this script"
- exit 1
-fi
-
-# Make sure tomcat is started with system locale
-if [ -r /etc/default/locale ]; then
- . /etc/default/locale
- export LANG
-fi
-
-. /lib/lsb/init-functions
-. /etc/rc.status
-
-
-# The following variables can be overwritten in $DEFAULT
-
-# Run Tomcat 6 as this user ID
-TOMCAT6_USER=tomcat6
-
-# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not
-# defined in $DEFAULT)
-JDK_DIRS="/usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-sun /usr/lib/jvm/java-1.5.0-sun /usr/lib/j2sdk1.5-sun /usr/lib/j2sdk1.5-ibm"
-
-# Look for the right JVM to use
-for jdir in $JDK_DIRS; do
- if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then
- JAVA_HOME="$jdir"
- fi
-done
-export JAVA_HOME
-
-# Directory for per-instance configuration files and webapps
-CATALINA_BASE=@MSENVIRON@
-
-# Use the Java security manager? (yes/no)
-TOMCAT6_SECURITY=no
-
-# Default Java options
-# Set java.awt.headless=true if JAVA_OPTS is not set so the
-# Xalan XSL transformer can work without X11 display on JDK 1.4+
-# It also looks like the default heap size of 64M is not enough for most cases
-# so the maximum heap size is set to 128M
-if [ -z "$JAVA_OPTS" ]; then
- JAVA_OPTS="-Djava.awt.headless=true -Xmx128M"
-fi
-
-# End of variables that can be overwritten in $DEFAULT
-
-# overwrite settings from default file
-if [ -f "$DEFAULT" ]; then
- . "$DEFAULT"
-fi
-
-if [ ! -f "$CATALINA_HOME/bin/bootstrap.jar" ]; then
- log_failure_msg "$NAME is not installed"
- exit 1
-fi
-
-[ -f "$DAEMON" ] || exit 0
-
-POLICY_CACHE="$CATALINA_BASE/work/catalina.policy"
-
-JAVA_OPTS="$JAVA_OPTS -Djava.endorsed.dirs=$CATALINA_HOME/endorsed -Dcatalina.base=$CATALINA_BASE -Dcatalina.home=$CATALINA_HOME -Djava.io.tmpdir=$JVM_TMP"
-
-# Set the JSP compiler if set in the tomcat6.default file
-if [ -n "$JSP_COMPILER" ]; then
- JAVA_OPTS="$JAVA_OPTS -Dbuild.compiler=$JSP_COMPILER"
-fi
-
-if [ "$TOMCAT6_SECURITY" = "yes" ]; then
- JAVA_OPTS="$JAVA_OPTS -Djava.security.manager -Djava.security.policy=$POLICY_CACHE"
-fi
-
-# Set juli LogManager if logging.properties is provided
-if [ -r "$CATALINA_BASE"/conf/logging.properties ]; then
- JAVA_OPTS="$JAVA_OPTS "-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager" "-Djava.util.logging.config.file="$CATALINA_BASE/conf/logging.properties"
-fi
-
-# Define other required variables
-CATALINA_PID="@PIDDIR@/$NAME.pid"
-BOOTSTRAP_CLASS=org.apache.catalina.startup.Bootstrap
-JSVC_CLASSPATH="/usr/share/java/commons-daemon.jar:$CATALINA_HOME/bin/bootstrap.jar"
-JSVC_CLASSPATH=$CLASSPATH:$JSVC_CLASSPATH
-
-# Look for Java Secure Sockets Extension (JSSE) JARs
-if [ -z "${JSSE_HOME}" -a -r "${JAVA_HOME}/jre/lib/jsse.jar" ]; then
- JSSE_HOME="${JAVA_HOME}/jre/"
-fi
-export JSSE_HOME
-
-case "$1" in
- start)
- if [ -z "$JAVA_HOME" ]; then
- log_failure_msg "no JDK found - please set JAVA_HOME"
- exit 1
- fi
-
- if [ ! -d "$CATALINA_BASE/conf" ]; then
- log_failure_msg "invalid CATALINA_BASE: $CATALINA_BASE"
- exit 1
- fi
-
- log_daemon_msg "Starting $DESC" "$NAME"
- if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
- --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
- >/dev/null; then
-
- # Regenerate POLICY_CACHE file
- umask 022
- echo "// AUTO-GENERATED FILE from /etc/tomcat6/policy.d/" \
- > "$POLICY_CACHE"
- echo "" >> "$POLICY_CACHE"
- if ls $CATALINA_BASE/conf/policy.d/*.policy > /dev/null 2>&1 ; then
- cat $CATALINA_BASE/conf/policy.d/*.policy \
- >> "$POLICY_CACHE"
- fi
-
- # Remove / recreate JVM_TMP directory
- rm -rf "$JVM_TMP"
- mkdir "$JVM_TMP" || {
- log_failure_msg "could not create JVM temporary directory"
- exit 1
- }
- chown $TOMCAT6_USER "$JVM_TMP"
- cd "$JVM_TMP"
-
-
- # fix storage issues on nfs mounts
- umask 000
- $DAEMON -user "$TOMCAT6_USER" -cp "$JSVC_CLASSPATH" \
- -outfile SYSLOG -errfile SYSLOG \
- -pidfile "$CATALINA_PID" $JAVA_OPTS "$BOOTSTRAP_CLASS"
-
- sleep 5
- if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
- --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
- >/dev/null; then
- log_end_msg 1
- else
- log_end_msg 0
- fi
- else
- log_progress_msg "(already running)"
- log_end_msg 0
- fi
- ;;
- stop)
- log_daemon_msg "Stopping $DESC" "$NAME"
- if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
- --user "$TOMCAT6_USER" --startas "$JAVA_HOME/bin/java" \
- >/dev/null; then
- log_progress_msg "(not running)"
- else
- $DAEMON -cp "$JSVC_CLASSPATH" -pidfile "$CATALINA_PID" \
- -stop "$BOOTSTRAP_CLASS"
- fi
- rm -rf "$JVM_TMP"
- log_end_msg 0
- ;;
- status)
- if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
- --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
- >/dev/null; then
-
- if [ -f "$CATALINA_PID" ]; then
- log_success_msg "$DESC is not running, but pid file exists."
- exit 1
- else
- log_success_msg "$DESC is not running."
- exit 3
- fi
- else
- log_success_msg "$DESC is running with pid `cat $CATALINA_PID`"
- fi
- ;;
- restart|force-reload)
- if start-stop-daemon --test --stop --pidfile "$CATALINA_PID" \
- --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
- >/dev/null; then
- $0 stop
- sleep 1
- fi
- $0 start
- ;;
- try-restart)
- if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
- --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
- >/dev/null; then
- $0 start
- fi
- ;;
- *)
- log_success_msg "Usage: $0 {start|stop|restart|try-restart|force-reload|status}"
- exit 1
- ;;
-esac
-
-exit 0
diff --git a/client/distro/sles/SYSCONFDIR/sysconfig/cloud-management.in b/client/distro/sles/SYSCONFDIR/sysconfig/cloud-management.in
deleted file mode 100644
index d22a6d5adc2..00000000000
--- a/client/distro/sles/SYSCONFDIR/sysconfig/cloud-management.in
+++ /dev/null
@@ -1,23 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# This file is loaded in /etc/init.d/vmopsmanagement
-# ATM we only do two things here:
-
-dummy=1 ; export TOMCAT_CFG=@MSCONF@/tomcat6.conf ; . @MSCONF@/tomcat6.conf
-#--------------------------
-
diff --git a/client/distro/ubuntu/SYSCONFDIR/init.d/cloud-management.in b/client/distro/ubuntu/SYSCONFDIR/init.d/cloud-management.in
deleted file mode 100755
index 4afa707a9e9..00000000000
--- a/client/distro/ubuntu/SYSCONFDIR/init.d/cloud-management.in
+++ /dev/null
@@ -1,244 +0,0 @@
-#!/bin/sh
-#
-# /etc/init.d/tomcat6 -- startup script for the Tomcat 6 servlet engine
-
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-### BEGIN INIT INFO
-# Provides: tomcat-vmops
-# Required-Start: $local_fs $remote_fs $network
-# Required-Stop: $local_fs $remote_fs $network
-# Should-Start: $named
-# Should-Stop: $named
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-# Short-Description: Start Tomcat (CloudStack).
-# Description: Start the Tomcat servlet engine that runs the CloudStack Management Server.
-### END INIT INFO
-
-PATH=/bin:/usr/bin:/sbin:/usr/sbin
-NAME=cloud-management
-DESC="CloudStack-specific Tomcat servlet engine"
-DAEMON=/usr/bin/jsvc
-CATALINA_HOME=@MSENVIRON@
-DEFAULT=@MSCONF@/tomcat6.conf
-JVM_TMP=/tmp/$NAME-temp
-
-# We have to explicitly set the HOME variable to the homedir from the user "cloud"
-# This is because various scripts run by the management server read the HOME variable
-# and fail when this init script is run manually.
-HOME=$(echo ~cloud)
-
-if [ `id -u` -ne 0 ]; then
- echo "You need root privileges to run this script"
- exit 1
-fi
-
-# Make sure tomcat is started with system locale
-if [ -r /etc/default/locale ]; then
- . /etc/default/locale
- export LANG
-fi
-
-. /lib/lsb/init-functions
-. /etc/default/rcS
-
-
-# The following variables can be overwritten in $DEFAULT
-
-# Run Tomcat 6 as this user ID
-TOMCAT6_USER=tomcat6
-
-# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not
-# defined in $DEFAULT)
-JDK_DIRS="/usr/lib/jvm/java-1.6.0-openjdk-amd64/ /usr/lib/jvm/java-1.6.0-openjdk-i386/ /usr/lib/jvm/java-1.6.0-openjdk/ /usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-sun"
-
-# Look for the right JVM to use
-for jdir in $JDK_DIRS; do
- if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then
- JAVA_HOME="$jdir"
- fi
-done
-export JAVA_HOME
-
-# Directory for per-instance configuration files and webapps
-CATALINA_BASE=@MSENVIRON@
-
-# Use the Java security manager? (yes/no)
-TOMCAT6_SECURITY=no
-
-# Default Java options
-# Set java.awt.headless=true if JAVA_OPTS is not set so the
-# Xalan XSL transformer can work without X11 display on JDK 1.4+
-# It also looks like the default heap size of 64M is not enough for most cases
-# so the maximum heap size is set to 128M
-if [ -z "$JAVA_OPTS" ]; then
- JAVA_OPTS="-Djava.awt.headless=true -Xmx128M"
-fi
-
-# End of variables that can be overwritten in $DEFAULT
-
-# overwrite settings from default file
-if [ -f "$DEFAULT" ]; then
- . "$DEFAULT"
-fi
-
-if [ ! -f "$CATALINA_HOME/bin/bootstrap.jar" ]; then
- log_failure_msg "$NAME is not installed"
- exit 1
-fi
-
-[ -f "$DAEMON" ] || exit 0
-
-POLICY_CACHE="$CATALINA_BASE/work/catalina.policy"
-
-JAVA_OPTS="$JAVA_OPTS -Djava.endorsed.dirs=$CATALINA_HOME/endorsed -Dcatalina.base=$CATALINA_BASE -Dcatalina.home=$CATALINA_HOME -Djava.io.tmpdir=$JVM_TMP"
-
-# Set the JSP compiler if set in the tomcat6.default file
-if [ -n "$JSP_COMPILER" ]; then
- JAVA_OPTS="$JAVA_OPTS -Dbuild.compiler=$JSP_COMPILER"
-fi
-
-if [ "$TOMCAT6_SECURITY" = "yes" ]; then
- JAVA_OPTS="$JAVA_OPTS -Djava.security.manager -Djava.security.policy=$POLICY_CACHE"
-fi
-
-# Set juli LogManager if logging.properties is provided
-if [ -r "$CATALINA_BASE"/conf/logging.properties ]; then
- JAVA_OPTS="$JAVA_OPTS "-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager" "-Djava.util.logging.config.file="$CATALINA_BASE/conf/logging.properties"
-fi
-
-# Define other required variables
-CATALINA_PID="@PIDDIR@/$NAME.pid"
-BOOTSTRAP_CLASS=org.apache.catalina.startup.Bootstrap
-JSVC_CLASSPATH="/usr/share/java/commons-daemon.jar:$CATALINA_HOME/bin/bootstrap.jar"
-JSVC_CLASSPATH=$CLASSPATH:$JSVC_CLASSPATH
-
-# Look for Java Secure Sockets Extension (JSSE) JARs
-if [ -z "${JSSE_HOME}" -a -r "${JAVA_HOME}/jre/lib/jsse.jar" ]; then
- JSSE_HOME="${JAVA_HOME}/jre/"
-fi
-export JSSE_HOME
-
-case "$1" in
- start)
- if [ -z "$JAVA_HOME" ]; then
- log_failure_msg "no JDK found - please set JAVA_HOME"
- exit 1
- fi
-
- if [ ! -d "$CATALINA_BASE/conf" ]; then
- log_failure_msg "invalid CATALINA_BASE: $CATALINA_BASE"
- exit 1
- fi
-
- log_daemon_msg "Starting $DESC" "$NAME"
- if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
- --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
- >/dev/null; then
-
- # Regenerate POLICY_CACHE file
- umask 022
- echo "// AUTO-GENERATED FILE from /etc/tomcat6/policy.d/" \
- > "$POLICY_CACHE"
- echo "" >> "$POLICY_CACHE"
- if ls $CATALINA_BASE/conf/policy.d/*.policy > /dev/null 2>&1 ; then
- cat $CATALINA_BASE/conf/policy.d/*.policy \
- >> "$POLICY_CACHE"
- fi
-
- # Remove / recreate JVM_TMP directory
- rm -rf "$JVM_TMP"
- mkdir "$JVM_TMP" || {
- log_failure_msg "could not create JVM temporary directory"
- exit 1
- }
- chown $TOMCAT6_USER "$JVM_TMP"
- cd "$JVM_TMP"
-
-
- # fix storage issues on nfs mounts
- umask 000
- $DAEMON -user "$TOMCAT6_USER" -cp "$JSVC_CLASSPATH" \
- -outfile SYSLOG -errfile SYSLOG \
- -pidfile "$CATALINA_PID" $JAVA_OPTS "$BOOTSTRAP_CLASS"
-
- sleep 5
- if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
- --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
- >/dev/null; then
- log_end_msg 1
- else
- log_end_msg 0
- fi
- else
- log_progress_msg "(already running)"
- log_end_msg 0
- fi
- ;;
- stop)
- log_daemon_msg "Stopping $DESC" "$NAME"
- if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
- --user "$TOMCAT6_USER" --startas "$JAVA_HOME/bin/java" \
- >/dev/null; then
- log_progress_msg "(not running)"
- else
- $DAEMON -cp "$JSVC_CLASSPATH" -pidfile "$CATALINA_PID" \
- -stop "$BOOTSTRAP_CLASS"
- fi
- rm -rf "$JVM_TMP"
- log_end_msg 0
- ;;
- status)
- if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
- --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
- >/dev/null; then
-
- if [ -f "$CATALINA_PID" ]; then
- log_success_msg "$DESC is not running, but pid file exists."
- exit 1
- else
- log_success_msg "$DESC is not running."
- exit 3
- fi
- else
- log_success_msg "$DESC is running with pid `cat $CATALINA_PID`"
- fi
- ;;
- restart|force-reload)
- if start-stop-daemon --test --stop --pidfile "$CATALINA_PID" \
- --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
- >/dev/null; then
- $0 stop
- sleep 1
- fi
- $0 start
- ;;
- try-restart)
- if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
- --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
- >/dev/null; then
- $0 start
- fi
- ;;
- *)
- log_success_msg "Usage: $0 {start|stop|restart|try-restart|force-reload|status}"
- exit 1
- ;;
-esac
-
-exit 0
diff --git a/client/pom.xml b/client/pom.xml
index 6dbffc43338..1545bfa11f2 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -13,11 +13,11 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-client-ui</artifactId>
<name>Apache CloudStack Client UI</name>
- <packaging>war</packaging>
+ <packaging>jar</packaging>
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
</parent>
<repositories>
@@ -28,6 +28,35 @@
</repositories>
<dependencies>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlets</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-webapp</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-jmx</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ <scope>runtime</scope>
+ </dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-framework-spring-module</artifactId>
@@ -63,6 +92,11 @@
<artifactId>cloud-plugin-acl-dynamic-role-based</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-plugin-ca-rootca</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-plugin-dedicated-resources</artifactId>
@@ -134,7 +168,7 @@
<version>${project.version}</version>
</dependency>
<dependency>
- <groupId>org.apache.cloudstack</groupId>
+ <groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-plugin-network-ovs</artifactId>
<version>${project.version}</version>
</dependency>
@@ -259,6 +293,11 @@
<artifactId>cloud-plugin-outofbandmanagement-driver-ipmitool</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-plugin-outofbandmanagement-driver-nested-cloudstack</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-mom-rabbitmq</artifactId>
@@ -274,6 +313,11 @@
<artifactId>cloud-mom-kafka</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-framework-ca</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-framework-ipc</artifactId>
@@ -399,6 +443,16 @@
<artifactId>cloud-plugin-database-quota</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-plugin-integrations-cloudian-connector</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-plugin-integrations-prometheus-exporter</artifactId>
+ <version>${project.version}</version>
+ </dependency>
</dependencies>
<build>
<plugins>
@@ -416,35 +470,18 @@
</execution>
</executions>
</plugin>
- <plugin>
- <groupId>com.googlecode.todomap</groupId>
- <artifactId>maven-jettygzip-plugin</artifactId>
- <version>0.0.4</version>
- <configuration>
- <webappDirectory>${project.build.directory}/generated-webapp</webappDirectory>
- <outputDirectory>${project.build.directory}/generated-webapp</outputDirectory>
- </configuration>
- <executions>
- <execution>
- <phase>prepare-package</phase>
- <goals>
- <goal>process</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-war-plugin</artifactId>
- <version>2.5</version>
+ <artifactId>maven-jar-plugin</artifactId>
<configuration>
- <webXml>./target/generated-webapp/WEB-INF/web.xml</webXml>
- <warSourceDirectory>./target/generated-webapp</warSourceDirectory>
<archive>
<manifest>
- <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+ <mainClass>org.apache.cloudstack.ServerDaemon</mainClass>
</manifest>
<manifestEntries>
+ <X-Git-Branch>${git.branch}</X-Git-Branch>
+ <X-Git-Tag>${git.tag}</X-Git-Tag>
+ <X-Git-Revision>${git.revision}</X-Git-Revision>
<Implementation-Revision>${git.revision}</Implementation-Revision>
<Implementation-Branch>${git.branch}</Implementation-Branch>
</manifestEntries>
@@ -455,13 +492,23 @@
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>${cs.jetty.version}</version>
- <dependencies>
+ <dependencies>
<!-- specify the dependent jdbc driver here -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${cs.mysql.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcprov-jdk15on</artifactId>
+ <version>${cs.bcprov.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcpkix-jdk15on</artifactId>
+ <version>${cs.bcprov.version}</version>
+ </dependency>
</dependencies>
<configuration>
<scanIntervalSeconds>0</scanIntervalSeconds>
@@ -473,13 +520,13 @@
<maxIdleTime>60000</maxIdleTime>
</connector>
</connectors>
- <webXml>${project.build.directory}/generated-webapp/WEB-INF/web.xml</webXml>
- <webAppSourceDirectory>${project.build.directory}/generated-webapp</webAppSourceDirectory>
+ <webXml>${project.build.directory}/classes/META-INF/webapp/WEB-INF/web.xml</webXml>
+ <webAppSourceDirectory>${project.build.directory}/classes/META-INF/webapp/</webAppSourceDirectory>
<webAppConfig>
<contextPath>/client</contextPath>
- <extraClasspath>${project.build.directory}/utilities/scripts/db/;${project.build.directory}/utilities/scripts/db/db/</extraClasspath>
+ <extraClasspath>${project.build.directory}/conf/;${project.build.directory}/common;${project.build.directory}/utilities/scripts/db/;${project.build.directory}/utilities/scripts/db/db/</extraClasspath>
+ <webInfIncludeJarPattern>.*/cloud.*jar$|.*/classes/.*</webInfIncludeJarPattern>
</webAppConfig>
-
<systemProperties>
<systemProperty>
<name>log4j.configuration</name>
@@ -488,15 +535,6 @@
</systemProperties>
</configuration>
</plugin>
- <plugin>
- <groupId>org.apache.tomcat.maven</groupId>
- <artifactId>tomcat7-maven-plugin</artifactId>
- <configuration>
- <path>/client</path>
- <tomcatWebXml>${basedir}/WEB-INF/web.xml</tomcatWebXml>
- <warSourceDirectory>${project.build.directory}/generated-webapp/</warSourceDirectory>
- </configuration>
- </plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
@@ -508,36 +546,20 @@
</goals>
<configuration>
<target>
- <copy todir="${basedir}/target/generated-webapp/WEB-INF/classes/scripts">
+ <copy todir="${project.build.directory}/common/scripts">
<fileset dir="${basedir}/../scripts"/>
</copy>
<!-- CLOUDSTACK-1304 -->
<chmod perm="755"
- file="${basedir}/target/generated-webapp/WEB-INF/classes/scripts/**" type="both"/>
- <copy todir="${basedir}/target/generated-webapp/WEB-INF/">
+ file="${project.build.directory}/common/scripts/**" type="both"/>
+ <copy todir="${project.build.directory}/classes/META-INF/webapp/WEB-INF/">
<fileset dir="${basedir}/WEB-INF/">
<include name="web.xml"/>
</fileset>
</copy>
- <copy todir="${basedir}/target/generated-webapp">
+ <copy todir="${project.build.directory}/classes/META-INF/webapp">
<fileset dir="${basedir}/../ui"/>
</copy>
- <copy overwrite="true" todir="${basedir}/target/generated-webapp/WEB-INF/classes">
- <fileset dir="${basedir}/tomcatconf">
- <include name="*.in"/>
- </fileset>
- <globmapper from="*.in" to="*"/>
- <filterchain>
- <filterreader classname="org.apache.tools.ant.filters.ReplaceTokens">
- <param type="propertiesfile" value="${cs.replace.properties}"/>
- </filterreader>
- </filterchain>
- </copy>
- <copy overwrite="true" todir="${basedir}/target/generated-webapp/WEB-INF/classes">
- <fileset dir="${basedir}/tomcatconf">
- <exclude name="*.in"/>
- </fileset>
- </copy>
<copy overwrite="true" todir="${basedir}/target/utilities/bin">
<fileset dir="${basedir}/../setup/bindir">
<include name="*.in"/>
@@ -571,7 +593,7 @@
</filterchain>
</copy>
<copy overwrite="true" todir="${basedir}/target/conf">
- <fileset dir="${basedir}/tomcatconf">
+ <fileset dir="${basedir}/conf">
<include name="*.in"/>
</fileset>
<globmapper from="*.in" to="*"/>
@@ -582,7 +604,7 @@
</filterchain>
</copy>
<copy overwrite="true" todir="${basedir}/target/conf">
- <fileset dir="${basedir}/tomcatconf">
+ <fileset dir="${basedir}/conf">
<exclude name="*.in"/>
</fileset>
</copy>
@@ -599,7 +621,7 @@
<target if="${noredist}">
<echo>test</echo>
<replaceregexp
- file="${basedir}/target/generated-webapp/WEB-INF/classes/environment.properties"
+ file="${basedir}/target/conf/environment.properties"
match="cloud-stack-components-specification=.*"
replace="cloud-stack-components-specification=components-nonoss.xml" byline="true"
/>
@@ -614,11 +636,11 @@
</goals>
<configuration>
<target if="${noredist}">
- <replaceregexp file="${basedir}/target/generated-webapp/WEB-INF/web.xml"
+ <replaceregexp file="${basedir}/target/classes/META-INF/webapp/WEB-INF/web.xml"
match="classpath:componentContext.xml"
replace="classpath:nonossComponentContext.xml" byline="true"/>
<copy overwrite="true"
- todir="${basedir}/target/generated-webapp/WEB-INF/classes/scripts">
+ todir="${basedir}/target/common/scripts">
<fileset dir="${basedir}/../plugins/network-elements/cisco-vnmc/scripts">
<include name="**/*"/>
</fileset>
@@ -649,11 +671,16 @@
<outputDirectory>${project.build.directory}/pythonlibs</outputDirectory>
</artifactItem>
<artifactItem>
- <groupId>org.jasypt</groupId>
- <artifactId>jasypt</artifactId>
- <version>1.9.2</version>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcprov-jdk15on</artifactId>
<overWrite>false</overWrite>
- <outputDirectory>${project.build.directory}/pythonlibs</outputDirectory>
+ <outputDirectory>${project.build.directory}/lib</outputDirectory>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcpkix-jdk15on</artifactId>
+ <overWrite>false</overWrite>
+ <outputDirectory>${project.build.directory}/lib</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
@@ -671,6 +698,70 @@
</execution>
</executions>
</plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <version>3.0.0</version>
+ <executions>
+ <execution>
+ <id>rebuild-war</id>
+ <phase>package</phase>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ <configuration>
+ <createDependencyReducedPom>false</createDependencyReducedPom>
+ <artifactSet>
+ <includes>
+ <include>*:*</include>
+ </includes>
+ <excludes>
+ <exclude>junit:junit</exclude>
+ <exclude>com.tngtech.java:junit-dataprovider</exclude>
+ <exclude>org.mockito:mockito-all</exclude>
+ <exclude>org.hamcrest:hamcrest-all</exclude>
+ <exclude>org.powermock:powermock-module-junit4</exclude>
+ <exclude>org.powermock:powermock-api-mockito</exclude>
+ <exclude>org.springframework:spring-test</exclude>
+ <exclude>org.apache.tomcat.embed:tomcat-embed-core</exclude>
+ <exclude>org.apache.geronimo.specs:geronimo-servlet_3.0_spec</exclude>
+ <exclude>org.apache.geronimo.specs:geronimo-javamail_1.4_spec</exclude>
+ <exclude>org.bouncycastle:bcprov-jdk15on</exclude>
+ <exclude>org.bouncycastle:bcpkix-jdk15on</exclude>
+ <exclude>mysql:mysql-connector-java</exclude>
+ </excludes>
+ </artifactSet>
+ <transformers>
+ <transformer implementation="org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformer" />
+ <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
+ <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+ <mainClass>org.apache.cloudstack.ServerDaemon</mainClass>
+ </transformer>
+ <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+ <resource>META-INF/spring.handlers</resource>
+ </transformer>
+ <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+ <resource>META-INF/spring.schemas</resource>
+ </transformer>
+ </transformers>
+ <filters>
+ <filter>
+ <artifact>*:*</artifact>
+ <excludes>
+ <exclude>META-INF/VERSION.txt</exclude>
+ <exclude>META-INF/LICENSE.txt</exclude>
+ <exclude>META-INF/*.SF</exclude>
+ <exclude>META-INF/*.DSA</exclude>
+ <exclude>META-INF/*.RSA</exclude>
+ <exclude>META-INF/MANIFEST.MF</exclude>
+ <exclude>META-INF/maven/**</exclude>
+ </excludes>
+ </filter>
+ </filters>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</build>
<profiles>
@@ -705,7 +796,7 @@
</goals>
<configuration>
<target>
- <copy todir="${basedir}/target/generated-webapp/WEB-INF/classes/vms">
+ <copy todir="${basedir}/target/common/vms">
<fileset dir="${basedir}/../systemvm/dist">
<include name="systemvm.zip"/>
<include name="systemvm.iso"/>
@@ -783,7 +874,6 @@
<get src="http://downloads.sourceforge.net/sevenzip/7z920-x64.msi" dest="target" verbose="false" usetimestamp="true"/>
<get src="https://www.python.org/ftp/python/2.7.6/python-2.7.6.amd64.msi" dest="target" verbose="false" usetimestamp="true"/>
<get src="http://dev.mysql.com/get/Downloads/MySQL-5.1/mysql-5.1.73-winx64.msi" dest="target" verbose="false" usetimestamp="true"/>
- <get src="http://mirror.sdunix.com/apache/tomcat/tomcat-6/v6.0.39/bin/apache-tomcat-6.0.39.exe" dest="target" verbose="false" usetimestamp="true"/>
<get src="http://downloads.sourceforge.net/project/cdrtoolswin/1.0/Binaries/CDR-Tools.exe?r=&ts=1398764640&use_mirror=kaz" dest="target" verbose="false" usetimestamp="true"/>
<get src="https://bootstrap.pypa.io/ez_setup.py" dest="target" verbose="false" usetimestamp="true"/>
</target>
@@ -1002,21 +1092,6 @@
</dependency>
</dependencies>
</profile>
- <profile>
- <id>midonet</id>
- <activation>
- <property>
- <name>midonet</name>
- </property>
- </activation>
- <dependencies>
- <dependency>
- <groupId>org.apache.cloudstack</groupId>
- <artifactId>cloud-plugin-network-midonet</artifactId>
- <version>${project.version}</version>
- </dependency>
- </dependencies>
- </profile>
<profile>
<id>srx</id>
<activation>
diff --git a/client/src/org/apache/cloudstack/ServerDaemon.java b/client/src/org/apache/cloudstack/ServerDaemon.java
new file mode 100644
index 00000000000..65e9a907cfd
--- /dev/null
+++ b/client/src/org/apache/cloudstack/ServerDaemon.java
@@ -0,0 +1,310 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+package org.apache.cloudstack;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.net.URL;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.servlet.DispatcherType;
+
+import org.apache.commons.daemon.Daemon;
+import org.apache.commons.daemon.DaemonContext;
+import org.eclipse.jetty.jmx.MBeanContainer;
+import org.eclipse.jetty.server.ForwardedRequestCustomizer;
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.NCSARequestLog;
+import org.eclipse.jetty.server.RequestLog;
+import org.eclipse.jetty.server.SecureRequestCustomizer;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.SslConnectionFactory;
+import org.eclipse.jetty.server.handler.HandlerCollection;
+import org.eclipse.jetty.server.handler.RequestLogHandler;
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.servlets.GzipFilter;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
+import org.eclipse.jetty.webapp.WebAppContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.cloud.utils.PropertiesUtil;
+import com.google.common.base.Strings;
+
+/***
+ * The ServerDaemon class implements the embedded server, it can be started either
+ * using JSVC or directly from the JAR along with additional jars not shaded in the uber-jar.
+ * Configuration parameters are read from server.properties file available on the classpath.
+ */
+public class ServerDaemon implements Daemon {
+ private static final Logger LOG = LoggerFactory.getLogger(ServerDaemon.class);
+ private static final String WEB_XML = "META-INF/webapp/WEB-INF/web.xml";
+
+ /////////////////////////////////////////////////////
+ /////////////// Server Properties ///////////////////
+ /////////////////////////////////////////////////////
+
+ private static final String BIND_INTERFACE = "bind.interface";
+ private static final String CONTEXT_PATH = "context.path";
+ private static final String HTTP_PORT = "http.port";
+ private static final String HTTPS_ENABLE = "https.enable";
+ private static final String HTTPS_PORT = "https.port";
+ private static final String KEYSTORE_FILE = "https.keystore";
+ private static final String KEYSTORE_PASSWORD = "https.keystore.password";
+ private static final String WEBAPP_DIR = "webapp.dir";
+ private static final String ACCESS_LOG = "access.log";
+
+ ////////////////////////////////////////////////////////
+ /////////////// Server Configuration ///////////////////
+ ////////////////////////////////////////////////////////
+
+ private Server server;
+
+ private int httpPort = 8080;
+ private int httpsPort = 8443;
+ private boolean httpsEnable = false;
+ private String accessLogFile = "access.log";
+ private String bindInterface = "";
+ private String contextPath = "/client";
+ private String keystoreFile;
+ private String keystorePassword;
+ private String webAppLocation;
+
+ //////////////////////////////////////////////////
+ /////////////// Public methods ///////////////////
+ //////////////////////////////////////////////////
+
+ public static void main(final String... anArgs) throws Exception {
+ final ServerDaemon daemon = new ServerDaemon();
+ daemon.init(null);
+ daemon.start();
+ }
+
+ @Override
+ public void init(final DaemonContext context) {
+ final File confFile = PropertiesUtil.findConfigFile("server.properties");
+ if (confFile == null) {
+ LOG.warn(String.format("Server configuration file not found. Initializing server daemon on %s:%s, with https.enabled=%s, https.port=%s, context.path=%s",
+ bindInterface, httpPort, httpsEnable, httpsPort, contextPath));
+ return;
+ }
+
+ LOG.info("Server configuration file found: " + confFile.getAbsolutePath());
+
+ try {
+ final Properties properties = PropertiesUtil.loadFromFile(confFile);
+ if (properties == null) {
+ return;
+ }
+ setBindInterface(properties.getProperty(BIND_INTERFACE, ""));
+ setContextPath(properties.getProperty(CONTEXT_PATH, "/client"));
+ setHttpPort(Integer.valueOf(properties.getProperty(HTTP_PORT, "8080")));
+ setHttpsEnable(Boolean.valueOf(properties.getProperty(HTTPS_ENABLE, "false")));
+ setHttpsPort(Integer.valueOf(properties.getProperty(HTTPS_PORT, "8443")));
+ setKeystoreFile(properties.getProperty(KEYSTORE_FILE));
+ setKeystorePassword(properties.getProperty(KEYSTORE_PASSWORD));
+ setWebAppLocation(properties.getProperty(WEBAPP_DIR));
+ setAccessLogFile(properties.getProperty(ACCESS_LOG, "access.log"));
+ } catch (final IOException e) {
+ LOG.warn("Failed to load configuration from server.properties file", e);
+ }
+ LOG.info(String.format("Initializing server daemon on %s:%s, with https.enabled=%s, https.port=%s, context.path=%s",
+ bindInterface, httpPort, httpsEnable, httpsPort, contextPath));
+ }
+
+ @Override
+ public void start() throws Exception {
+ // Thread pool
+ final QueuedThreadPool threadPool = new QueuedThreadPool();
+ threadPool.setMinThreads(10);
+ threadPool.setMaxThreads(500);
+
+ // Jetty Server
+ server = new Server(threadPool);
+
+ // Setup Scheduler
+ server.addBean(new ScheduledExecutorScheduler());
+
+ // Setup JMX
+ final MBeanContainer mbeanContainer = new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
+ server.addBean(mbeanContainer);
+
+ // HTTP config
+ final HttpConfiguration httpConfig = new HttpConfiguration();
+ httpConfig.addCustomizer( new ForwardedRequestCustomizer() );
+ httpConfig.setSecureScheme("https");
+ httpConfig.setSecurePort(httpsPort);
+ httpConfig.setOutputBufferSize(32768);
+ httpConfig.setRequestHeaderSize(8192);
+ httpConfig.setResponseHeaderSize(8192);
+ httpConfig.setSendServerVersion(false);
+ httpConfig.setSendDateHeader(false);
+
+ // HTTP Connector
+ final ServerConnector httpConnector = new ServerConnector(server, new HttpConnectionFactory(httpConfig));
+ httpConnector.setPort(httpPort);
+ httpConnector.setHost(bindInterface);
+ httpConnector.setIdleTimeout(30000);
+ server.addConnector(httpConnector);
+
+ // Setup handlers
+ server.setHandler(createHandlers());
+
+ // Extra config options
+ server.setStopAtShutdown(true);
+
+ // Configure SSL
+ if (httpsEnable && !Strings.isNullOrEmpty(keystoreFile) && new File(keystoreFile).exists()) {
+ // SSL Context
+ final SslContextFactory sslContextFactory = new SslContextFactory();
+ // Define keystore path and passwords
+ sslContextFactory.setKeyStorePath(keystoreFile);
+ sslContextFactory.setKeyStorePassword(keystorePassword);
+ sslContextFactory.setKeyManagerPassword(keystorePassword);
+
+ // HTTPS config
+ final HttpConfiguration httpsConfig = new HttpConfiguration(httpConfig);
+ httpsConfig.addCustomizer(new SecureRequestCustomizer());
+
+ // HTTPS connector
+ final ServerConnector sslConnector = new ServerConnector(server,
+ new SslConnectionFactory(sslContextFactory, "http/1.1"),
+ new HttpConnectionFactory(httpsConfig));
+ sslConnector.setPort(httpsPort);
+ sslConnector.setHost(bindInterface);
+ server.addConnector(sslConnector);
+ }
+
+ server.start();
+ server.join();
+ }
+
+ @Override
+ public void stop() throws Exception {
+ server.stop();
+ }
+
+ @Override
+ public void destroy() {
+ server.destroy();
+ }
+
+ ///////////////////////////////////////////////////
+ /////////////// Private methods ///////////////////
+ ///////////////////////////////////////////////////
+
+ private HandlerCollection createHandlers() {
+ final WebAppContext webApp = new WebAppContext();
+ webApp.setContextPath(contextPath);
+ webApp.setInitParameter("org.eclipse.jetty.servlet.Default.dirAllowed", "false");
+
+ final FilterHolder filter = webApp.addFilter(GzipFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
+ final Map<String, String> params = new HashMap<>();
+ params.put("mimeTypes", "text/html,text/xml,text/css,text/plain,text/javascript,application/javascript,application/json,application/xml");
+ params.put("methods", "GET,POST");
+ params.put("deflateCompressionLevel", "9");
+ filter.setInitParameters(params);
+
+ if (Strings.isNullOrEmpty(webAppLocation)) {
+ webApp.setWar(getShadedWarUrl());
+ } else {
+ webApp.setWar(webAppLocation);
+ }
+
+ final RequestLogHandler log = new RequestLogHandler();
+ log.setRequestLog(createRequestLog());
+
+ final HandlerCollection handlerCollection = new HandlerCollection();
+ handlerCollection.addHandler(log);
+ handlerCollection.addHandler(webApp);
+
+ return handlerCollection;
+ }
+
+ private RequestLog createRequestLog() {
+ final NCSARequestLog log = new NCSARequestLog();
+ final File logPath = new File(accessLogFile);
+ final File parentFile = logPath.getParentFile();
+ if (parentFile != null) {
+ parentFile.mkdirs();
+ }
+ log.setFilename(logPath.getPath());
+ log.setAppend(true);
+ log.setLogTimeZone("GMT");
+ log.setLogLatency(true);
+ return log;
+ }
+
+ private URL getResource(String aResource) {
+ return Thread.currentThread().getContextClassLoader().getResource(aResource);
+ }
+
+ private String getShadedWarUrl() {
+ final String urlStr = getResource(WEB_XML).toString();
+ return urlStr.substring(0, urlStr.length() - 15);
+ }
+
+ ///////////////////////////////////////////
+ /////////////// Setters ///////////////////
+ ///////////////////////////////////////////
+
+ public void setBindInterface(String bindInterface) {
+ this.bindInterface = bindInterface;
+ }
+
+ public void setHttpPort(int httpPort) {
+ this.httpPort = httpPort;
+ }
+
+ public void setHttpsPort(int httpsPort) {
+ this.httpsPort = httpsPort;
+ }
+
+ public void setContextPath(String contextPath) {
+ this.contextPath = contextPath;
+ }
+
+ public void setHttpsEnable(boolean httpsEnable) {
+ this.httpsEnable = httpsEnable;
+ }
+
+ public void setKeystoreFile(String keystoreFile) {
+ this.keystoreFile = keystoreFile;
+ }
+
+ public void setKeystorePassword(String keystorePassword) {
+ this.keystorePassword = keystorePassword;
+ }
+
+ public void setAccessLogFile(String accessLogFile) {
+ this.accessLogFile = accessLogFile;
+ }
+
+ public void setWebAppLocation(String webAppLocation) {
+ this.webAppLocation = webAppLocation;
+ }
+}
diff --git a/client/tomcatconf/catalina.policy.in b/client/tomcatconf/catalina.policy.in
deleted file mode 100644
index 4bbfbf29058..00000000000
--- a/client/tomcatconf/catalina.policy.in
+++ /dev/null
@@ -1,180 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to You under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// ============================================================================
-// catalina.corepolicy - Security Policy Permissions for Tomcat 6
-//
-// This file contains a default set of security policies to be enforced (by the
-// JVM) when Catalina is executed with the "-security" option. In addition
-// to the permissions granted here, the following additional permissions are
-// granted to the codebase specific to each web application:
-//
-// * Read access to the document root directory
-//
-// $Id: catalina.policy 899134 2010-01-14 09:44:28Z rjung $
-// ============================================================================
-
-
-// ========== SYSTEM CODE PERMISSIONS =========================================
-
-
-// These permissions apply to javac
-grant codeBase "file:${java.home}/lib/-" {
- permission java.security.AllPermission;
-};
-
-// These permissions apply to all shared system extensions
-grant codeBase "file:${java.home}/jre/lib/ext/-" {
- permission java.security.AllPermission;
-};
-
-// These permissions apply to javac when ${java.home] points at $JAVA_HOME/jre
-grant codeBase "file:${java.home}/../lib/-" {
- permission java.security.AllPermission;
-};
-
-// These permissions apply to all shared system extensions when
-// ${java.home} points at $JAVA_HOME/jre
-grant codeBase "file:${java.home}/lib/ext/-" {
- permission java.security.AllPermission;
-};
-
-
-// ========== CATALINA CODE PERMISSIONS =======================================
-
-
-// These permissions apply to the daemon code
-grant codeBase "file:${catalina.home}/bin/commons-daemon.jar" {
- permission java.security.AllPermission;
-};
-
-// These permissions apply to the logging API
-grant codeBase "file:${catalina.home}/bin/tomcat-juli.jar" {
- permission java.util.PropertyPermission "java.util.logging.config.class", "read";
- permission java.util.PropertyPermission "java.util.logging.config.file", "read";
- permission java.io.FilePermission "${java.home}${file.separator}lib${file.separator}logging.properties", "read";
- permission java.lang.RuntimePermission "shutdownHooks";
- permission java.io.FilePermission "${catalina.base}${file.separator}conf${file.separator}logging.properties", "read";
- permission java.util.PropertyPermission "catalina.base", "read";
- permission java.util.logging.LoggingPermission "control";
- permission java.io.FilePermission "${catalina.base}${file.separator}logs", "read, write";
- permission java.io.FilePermission "${catalina.base}${file.separator}logs${file.separator}*", "read, write";
- permission java.lang.RuntimePermission "getClassLoader";
- permission java.lang.RuntimePermission "setContextClassLoader";
- // To enable per context logging configuration, permit read access to the appropriate file.
- // Be sure that the logging configuration is secure before enabling such access
- // eg for the examples web application:
- // permission java.io.FilePermission "${catalina.base}${file.separator}webapps${file.separator}examples${file.separator}WEB-INF${file.separator}classes${file.separator}logging.properties", "read";
-};
-
-// These permissions apply to the server startup code
-grant codeBase "file:${catalina.home}/bin/bootstrap.jar" {
- permission java.security.AllPermission;
-};
-
-// These permissions apply to the servlet API classes
-// and those that are shared across all class loaders
-// located in the "lib" directory
-grant codeBase "file:${catalina.home}/lib/-" {
- permission java.security.AllPermission;
-};
-
-
-// ========== WEB APPLICATION PERMISSIONS =====================================
-
-
-// These permissions are granted by default to all web applications
-// In addition, a web application will be given a read FilePermission
-// and JndiPermission for all files and directories in its document root.
-grant {
- // Required for JNDI lookup of named JDBC DataSource's and
- // javamail named MimePart DataSource used to send mail
- permission java.util.PropertyPermission "java.home", "read";
- permission java.util.PropertyPermission "java.naming.*", "read";
- permission java.util.PropertyPermission "javax.sql.*", "read";
-
- // OS Specific properties to allow read access
- permission java.util.PropertyPermission "os.name", "read";
- permission java.util.PropertyPermission "os.version", "read";
- permission java.util.PropertyPermission "os.arch", "read";
- permission java.util.PropertyPermission "file.separator", "read";
- permission java.util.PropertyPermission "path.separator", "read";
- permission java.util.PropertyPermission "line.separator", "read";
-
- // JVM properties to allow read access
- permission java.util.PropertyPermission "java.version", "read";
- permission java.util.PropertyPermission "java.vendor", "read";
- permission java.util.PropertyPermission "java.vendor.url", "read";
- permission java.util.PropertyPermission "java.class.version", "read";
- permission java.util.PropertyPermission "java.specification.version", "read";
- permission java.util.PropertyPermission "java.specification.vendor", "read";
- permission java.util.PropertyPermission "java.specification.name", "read";
-
- permission java.util.PropertyPermission "java.vm.specification.version", "read";
- permission java.util.PropertyPermission "java.vm.specification.vendor", "read";
- permission java.util.PropertyPermission "java.vm.specification.name", "read";
- permission java.util.PropertyPermission "java.vm.version", "read";
- permission java.util.PropertyPermission "java.vm.vendor", "read";
- permission java.util.PropertyPermission "java.vm.name", "read";
-
- // Required for OpenJMX
- permission java.lang.RuntimePermission "getAttribute";
-
- // Allow read of JAXP compliant XML parser debug
- permission java.util.PropertyPermission "jaxp.debug", "read";
-
- // Precompiled JSPs need access to these packages.
- permission java.lang.RuntimePermission "accessClassInPackage.org.apache.jasper.el";
- permission java.lang.RuntimePermission "accessClassInPackage.org.apache.jasper.runtime";
- permission java.lang.RuntimePermission "accessClassInPackage.org.apache.jasper.runtime.*";
-
- // Precompiled JSPs need access to these system properties.
- permission java.util.PropertyPermission "org.apache.jasper.runtime.BodyContentImpl.LIMIT_BUFFER", "read";
- permission java.util.PropertyPermission "org.apache.el.parser.COERCE_TO_ZERO", "read";
-};
-
-
-// You can assign additional permissions to particular web applications by
-// adding additional "grant" entries here, based on the code base for that
-// application, /WEB-INF/classes/, or /WEB-INF/lib/ jar files.
-//
-// Different permissions can be granted to JSP pages, classes loaded from
-// the /WEB-INF/classes/ directory, all jar files in the /WEB-INF/lib/
-// directory, or even to individual jar files in the /WEB-INF/lib/ directory.
-//
-// For instance, assume that the standard "examples" application
-// included a JDBC driver that needed to establish a network connection to the
-// corresponding database and used the scrape taglib to get the weather from
-// the NOAA web server. You might create a "grant" entries like this:
-//
-// The permissions granted to the context root directory apply to JSP pages.
-// grant codeBase "file:${catalina.home}/webapps/examples/-" {
-// permission java.net.SocketPermission "dbhost.mycompany.com:5432", "connect";
-// permission java.net.SocketPermission "*.noaa.gov:80", "connect";
-// };
-//
-// The permissions granted to the context WEB-INF/classes directory
-// grant codeBase "file:${catalina.home}/webapps/examples/WEB-INF/classes/-" {
-// };
-//
-// The permission granted to your JDBC driver
-// grant codeBase "jar:file:${catalina.home}/webapps/examples/WEB-INF/lib/driver.jar!/-" {
-// permission java.net.SocketPermission "dbhost.mycompany.com:5432", "connect";
-// };
-// The permission granted to the scrape taglib
-// grant codeBase "jar:file:${catalina.home}/webapps/examples/WEB-INF/lib/scrape.jar!/-" {
-// permission java.net.SocketPermission "*.noaa.gov:80", "connect";
-// };
-
diff --git a/client/tomcatconf/catalina.properties.in b/client/tomcatconf/catalina.properties.in
deleted file mode 100644
index e0baf61261d..00000000000
--- a/client/tomcatconf/catalina.properties.in
+++ /dev/null
@@ -1,81 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-#
-# List of comma-separated packages that start with or equal this string
-# will cause a security exception to be thrown when
-# passed to checkPackageAccess unless the
-# corresponding RuntimePermission ("accessClassInPackage."+package) has
-# been granted.
-package.access=sun.,org.apache.catalina.,org.apache.coyote.,org.apache.tomcat.,org.apache.jasper.,sun.beans.
-#
-# List of comma-separated packages that start with or equal this string
-# will cause a security exception to be thrown when
-# passed to checkPackageDefinition unless the
-# corresponding RuntimePermission ("defineClassInPackage."+package) has
-# been granted.
-#
-# by default, no packages are restricted for definition, and none of
-# the class loaders supplied with the JDK call checkPackageDefinition.
-#
-package.definition=sun.,java.,org.apache.catalina.,org.apache.coyote.,org.apache.tomcat.,org.apache.jasper.
-
-#
-#
-# List of comma-separated paths defining the contents of the "common"
-# classloader. Prefixes should be used to define what is the repository type.
-# Path may be relative to the CATALINA_HOME or CATALINA_BASE path or absolute.
-# If left as blank,the JVM system loader will be used as Catalina's "common"
-# loader.
-# Examples:
-# "foo": Add this folder as a class repository
-# "foo/*.jar": Add all the JARs of the specified folder as class
-# repositories
-# "foo/bar.jar": Add bar.jar as a class repository
-common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar,/usr/share/java/mysql-connector-java.jar,/usr/share/cloudstack-mysql-ha/lib/*.jar
-
-#
-# List of comma-separated paths defining the contents of the "server"
-# classloader. Prefixes should be used to define what is the repository type.
-# Path may be relative to the CATALINA_HOME or CATALINA_BASE path or absolute.
-# If left as blank, the "common" loader will be used as Catalina's "server"
-# loader.
-# Examples:
-# "foo": Add this folder as a class repository
-# "foo/*.jar": Add all the JARs of the specified folder as class
-# repositories
-# "foo/bar.jar": Add bar.jar as a class repository
-server.loader=
-
-#
-# List of comma-separated paths defining the contents of the "shared"
-# classloader. Prefixes should be used to define what is the repository type.
-# Path may be relative to the CATALINA_BASE path or absolute. If left as blank,
-# the "common" loader will be used as Catalina's "shared" loader.
-# Examples:
-# "foo": Add this folder as a class repository
-# "foo/*.jar": Add all the JARs of the specified folder as class
-# repositories
-# "foo/bar.jar": Add bar.jar as a class repository
-# Please note that for single jars, e.g. bar.jar, you need the URL form
-# starting with file:.
-shared.loader=
-
-#
-# String cache configuration.
-tomcat.util.buf.StringCache.byte.enabled=true
-#tomcat.util.buf.StringCache.char.enabled=true
-#tomcat.util.buf.StringCache.trainThreshold=500000
-#tomcat.util.buf.StringCache.cacheSize=5000
diff --git a/client/tomcatconf/classpath.conf.in b/client/tomcatconf/classpath.conf.in
deleted file mode 100644
index ecdd12a630e..00000000000
--- a/client/tomcatconf/classpath.conf.in
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/bash
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-SYSTEMJARS="@SYSTEMJARS@"
-SCP=$(build-classpath $SYSTEMJARS 2>/dev/null) ; if [ $? != 0 ] ; then export SCP="@SYSTEMCLASSPATH@" ; fi
-MCP="@MSCLASSPATH@"
-DCP="@DEPSCLASSPATH@"
-CLASSPATH=$SCP:$DCP:$MCP:@MSCONF@:@SETUPDATADIR@
-for jarfile in "@PREMIUMJAVADIR@"/* ; do
- if [ ! -e "$jarfile" ] ; then continue ; fi
- CLASSPATH=$jarfile:$CLASSPATH
-done
-for plugin in "@PLUGINJAVADIR@"/* ; do
- if [ ! -e "$plugin" ] ; then continue ; fi
- CLASSPATH=$plugin:$CLASSPATH
-done
-for vendorconf in "@MSCONF@"/vendor/* ; do
- if [ ! -d "$vendorconf" ] ; then continue ; fi
- CLASSPATH=$vendorconf:$CLASSPATH
-done
-export CLASSPATH
-if ([ -z "$JAVA_HOME" ] || [ ! -d "$JAVA_HOME" ]) && [ -d /usr/lib/jvm/jre-1.8.0 ]; then
- export JAVA_HOME=/usr/lib/jvm/jre-1.8.0
-fi
-PATH=$JAVA_HOME/bin:/sbin:/usr/sbin:$PATH
-export PATH
diff --git a/client/tomcatconf/cloudmanagementserver.keystore b/client/tomcatconf/cloudmanagementserver.keystore
deleted file mode 100644
index 3ee4d13565a..00000000000
Binary files a/client/tomcatconf/cloudmanagementserver.keystore and /dev/null differ
diff --git a/client/tomcatconf/context.xml.in b/client/tomcatconf/context.xml.in
deleted file mode 100644
index a78215c7c21..00000000000
--- a/client/tomcatconf/context.xml.in
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- The contents of this file will be loaded for each web application -->
-<Context allowLinking="true" useHttpOnly="true">
-
- <!-- Default set of monitored resources -->
- <WatchedResource>WEB-INF/web.xml</WatchedResource>
-
- <!-- Uncomment this to disable session persistence across Tomcat restarts -->
- <!--
- <Manager pathname="" />
- -->
-
- <!-- Uncomment this to enable Comet connection tacking (provides events
- on session expiration as well as webapp lifecycle) -->
- <!--
- <Valve className="org.apache.catalina.valves.CometConnectionManagerValve" />
- -->
-
-</Context>
diff --git a/client/tomcatconf/logging.properties.in b/client/tomcatconf/logging.properties.in
deleted file mode 100644
index 68be2d7f457..00000000000
--- a/client/tomcatconf/logging.properties.in
+++ /dev/null
@@ -1,64 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-handlers = 1catalina.org.apache.juli.FileHandler, 2localhost.org.apache.juli.FileHandler, 3manager.org.apache.juli.FileHandler, 4host-manager.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
-
-.handlers = 1catalina.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
-
-############################################################
-# Handler specific properties.
-# Describes specific configuration info for Handlers.
-############################################################
-
-1catalina.org.apache.juli.FileHandler.level = FINE
-1catalina.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
-1catalina.org.apache.juli.FileHandler.prefix = catalina.
-
-2localhost.org.apache.juli.FileHandler.level = FINE
-2localhost.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
-2localhost.org.apache.juli.FileHandler.prefix = localhost.
-
-3manager.org.apache.juli.FileHandler.level = FINE
-3manager.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
-3manager.org.apache.juli.FileHandler.prefix = manager.
-
-4host-manager.org.apache.juli.FileHandler.level = FINE
-4host-manager.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
-4host-manager.org.apache.juli.FileHandler.prefix = host-manager.
-
-java.util.logging.ConsoleHandler.level = FINE
-java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
-
-
-############################################################
-# Facility specific properties.
-# Provides extra control for each logger.
-############################################################
-
-org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = INFO
-org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = 2localhost.org.apache.juli.FileHandler
-
-org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].level = INFO
-org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].handlers = 3manager.org.apache.juli.FileHandler
-
-org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager].level = INFO
-org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager].handlers = 4host-manager.org.apache.juli.FileHandler
-
-# For example, set the com.xyz.foo logger to only log SEVERE
-# messages:
-#org.apache.catalina.startup.ContextConfig.level = FINE
-#org.apache.catalina.startup.HostConfig.level = FINE
-#org.apache.catalina.session.ManagerBase.level = FINE
-#org.apache.catalina.core.AprLifecycleListener.level=FINE
diff --git a/client/tomcatconf/server-nonssl.xml.in b/client/tomcatconf/server-nonssl.xml.in
deleted file mode 100755
index 4272a28428b..00000000000
--- a/client/tomcatconf/server-nonssl.xml.in
+++ /dev/null
@@ -1,149 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- Note: A "Server" is not itself a "Container", so you may not
- define subcomponents such as "Valves" at this level.
- Documentation at /docs/config/server.html
- -->
-<Server port="8005" shutdown="SHUTDOWN">
-
- <!--APR library loader. Documentation at /docs/apr.html -->
- <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
- <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
- <Listener className="org.apache.catalina.core.JasperListener" />
- <!-- JMX Support for the Tomcat server. Documentation at /docs/non-existent.html -->
- <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
- <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
-
- <!-- Global JNDI resources
- Documentation at /docs/jndi-resources-howto.html
- -->
- <GlobalNamingResources>
- <!-- Editable user database that can also be used by
- UserDatabaseRealm to authenticate users
- -->
- <Resource name="UserDatabase" auth="Container"
- type="org.apache.catalina.UserDatabase"
- description="User database that can be updated and saved"
- factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
- pathname="conf/tomcat-users.xml" />
- </GlobalNamingResources>
-
- <!-- A "Service" is a collection of one or more "Connectors" that share
- a single "Container" Note: A "Service" is not itself a "Container",
- so you may not define subcomponents such as "Valves" at this level.
- Documentation at /docs/config/service.html
- -->
- <Service name="Catalina">
-
- <!--The connectors can use a shared executor, you can define one or more named thread pools-->
- <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
- maxThreads="150" minSpareThreads="25"/>
-
-
- <!-- A "Connector" represents an endpoint by which requests are received
- and responses are returned. Documentation at :
- Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
- Java AJP Connector: /docs/config/ajp.html
- APR (HTTP/AJP) Connector: /docs/apr.html
- Define a non-SSL HTTP/1.1 Connector on port 8080
- -->
- <!--
- <Connector port="8080" protocol="HTTP/1.1"
- connectionTimeout="20000"
- redirectPort="8443" />
- -->
- <!-- A "Connector" using the shared thread pool-->
- <Connector executor="tomcatThreadPool" URIEncoding="UTF-8"
- port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
- connectionTimeout="20000" disableUploadTimeout="true"
- acceptCount="150" enableLookups="false" maxThreads="150"
- maxHttpHeaderSize="8192" redirectPort="8443" />
-
-
- <!-- Define a SSL HTTP/1.1 Connector on port 8443
- This connector uses the JSSE configuration, when using APR, the
- connector should be using the OpenSSL style configuration
- described in the APR documentation -->
- <!--
- <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
- maxThreads="150" scheme="https" secure="true"
- clientAuth="false" sslProtocol="TLS" sslEnabledProtocols="TLSv1.2,TLSv1.1"
- keystoreType="PKCS12"
- keystoreFile="conf/cloud-localhost.pk12"
- keystorePass="password"
- />
- -->
-
- <!-- Define an AJP 1.3 Connector on port 20400 -->
- <Connector port="20400" protocol="AJP/1.3" redirectPort="8443" />
-
-
- <!-- An Engine represents the entry point (within Catalina) that processes
- every request. The Engine implementation for Tomcat stand alone
- analyzes the HTTP headers included with the request, and passes them
- on to the appropriate Host (virtual host).
- Documentation at /docs/config/engine.html -->
-
- <!-- You should set jvmRoute to support load-balancing via AJP ie :
- <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
- -->
- <Engine name="Catalina" defaultHost="localhost">
-
- <!--For clustering, please take a look at documentation at:
- /docs/cluster-howto.html (simple how to)
- /docs/config/cluster.html (reference documentation) -->
- <!--
- <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
- -->
-
- <!-- The request dumper valve dumps useful debugging information about
- the request and response data received and sent by Tomcat.
- Documentation at: /docs/config/valve.html -->
- <!--
- <Valve className="org.apache.catalina.valves.RequestDumperValve"/>
- -->
-
- <!-- This Realm uses the UserDatabase configured in the global JNDI
- resources under the key "UserDatabase". Any edits
- that are performed against this UserDatabase are immediately
- available for use by the Realm. -->
- <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
- resourceName="UserDatabase"/>
-
- <!-- Define the default virtual host
- Note: XML Schema validation will not work with Xerces 2.2.
- -->
- <Host name="localhost" appBase="webapps"
- unpackWARs="true" autoDeploy="true"
- xmlValidation="false" xmlNamespaceAware="false">
-
- <!-- SingleSignOn valve, share authentication between web applications
- Documentation at: /docs/config/valve.html -->
- <!--
- <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
- -->
-
- <!-- Access log processes all example.
- Documentation at: /docs/config/valve.html -->
- <Valve className="org.apache.catalina.valves.FastCommonAccessLogValve" directory="logs"
- prefix="access_log." suffix=".txt" pattern="common" resolveHosts="false"/>
-
- </Host>
- </Engine>
- </Service>
-</Server>
diff --git a/client/tomcatconf/server-ssl.xml.in b/client/tomcatconf/server-ssl.xml.in
deleted file mode 100755
index 595879fbfd1..00000000000
--- a/client/tomcatconf/server-ssl.xml.in
+++ /dev/null
@@ -1,157 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- Note: A "Server" is not itself a "Container", so you may not
- define subcomponents such as "Valves" at this level.
- Documentation at /docs/config/server.html
- -->
-<Server port="8005" shutdown="SHUTDOWN">
-
- <!--APR library loader. Documentation at /docs/apr.html -->
- <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
- <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
- <Listener className="org.apache.catalina.core.JasperListener" />
- <!-- JMX Support for the Tomcat server. Documentation at /docs/non-existent.html -->
- <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
- <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
-
- <!-- Global JNDI resources
- Documentation at /docs/jndi-resources-howto.html
- -->
- <GlobalNamingResources>
- <!-- Editable user database that can also be used by
- UserDatabaseRealm to authenticate users
- -->
- <Resource name="UserDatabase" auth="Container"
- type="org.apache.catalina.UserDatabase"
- description="User database that can be updated and saved"
- factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
- pathname="conf/tomcat-users.xml" />
- </GlobalNamingResources>
-
- <!-- A "Service" is a collection of one or more "Connectors" that share
- a single "Container" Note: A "Service" is not itself a "Container",
- so you may not define subcomponents such as "Valves" at this level.
- Documentation at /docs/config/service.html
- -->
- <Service name="Catalina">
-
- <!--The connectors can use a shared executor, you can define one or more named thread pools-->
- <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
- maxThreads="150" minSpareThreads="25"/>
-
-
- <!-- A "Connector" represents an endpoint by which requests are received
- and responses are returned. Documentation at :
- Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
- Java AJP Connector: /docs/config/ajp.html
- APR (HTTP/AJP) Connector: /docs/apr.html
- Define a non-SSL HTTP/1.1 Connector on port 8080
- -->
- <!--
- <Connector port="8080" protocol="HTTP/1.1"
- connectionTimeout="20000"
- redirectPort="8443" />
- -->
- <!-- A "Connector" using the shared thread pool-->
- <!--
- <Connector executor="tomcatThreadPool"
- port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
- connectionTimeout="20000" disableUploadTimeout="true"
- acceptCount="150" enableLookups="false" maxThreads="150"
- maxHttpHeaderSize="8192" redirectPort="8443" />
- -->
- <!-- Define a SSL HTTP/1.1 Connector on port 8443
- This connector uses the JSSE configuration, when using APR, the
- connector should be using the OpenSSL style configuration
- described in the APR documentation -->
- <!--
- <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
- maxThreads="150" scheme="https" secure="true"
- clientAuth="false" sslProtocol="TLS" sslEnabledProtocols="TLSv1.2,TLSv1.1"
- keystoreType="PKCS12"
- keystoreFile="conf/cloud-localhost.pk12"
- keystorePass="password"
- />
- -->
-
- <!-- Listen on 6443 instead of 8443 because tomcat6 will change 8443 to a random one when CATALINA_HOME is not /usr/share/tomcat6 -->
- <Connector port="6443" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true"
- maxThreads="150" scheme="https" secure="true" URIEncoding="UTF-8"
- clientAuth="false" sslProtocol="TLS"
- keystoreType="JKS"
- keystoreFile="/etc/cloudstack/management/cloudmanagementserver.keystore"
- keystorePass="vmops.com"/>
-
- <!-- Define an AJP 1.3 Connector on port 20400 -->
- <Connector port="20400" protocol="AJP/1.3" redirectPort="6443" />
-
-
- <!-- An Engine represents the entry point (within Catalina) that processes
- every request. The Engine implementation for Tomcat stand alone
- analyzes the HTTP headers included with the request, and passes them
- on to the appropriate Host (virtual host).
- Documentation at /docs/config/engine.html -->
-
- <!-- You should set jvmRoute to support load-balancing via AJP ie :
- <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
- -->
- <Engine name="Catalina" defaultHost="localhost">
-
- <!--For clustering, please take a look at documentation at:
- /docs/cluster-howto.html (simple how to)
- /docs/config/cluster.html (reference documentation) -->
- <!--
- <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
- -->
-
- <!-- The request dumper valve dumps useful debugging information about
- the request and response data received and sent by Tomcat.
- Documentation at: /docs/config/valve.html -->
- <!--
- <Valve className="org.apache.catalina.valves.RequestDumperValve"/>
- -->
-
- <!-- This Realm uses the UserDatabase configured in the global JNDI
- resources under the key "UserDatabase". Any edits
- that are performed against this UserDatabase are immediately
- available for use by the Realm. -->
- <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
- resourceName="UserDatabase"/>
-
- <!-- Define the default virtual host
- Note: XML Schema validation will not work with Xerces 2.2.
- -->
- <Host name="localhost" appBase="webapps"
- unpackWARs="true" autoDeploy="true"
- xmlValidation="false" xmlNamespaceAware="false">
-
- <!-- SingleSignOn valve, share authentication between web applications
- Documentation at: /docs/config/valve.html -->
- <!--
- <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
- -->
-
- <!-- Access log processes all example.
- Documentation at: /docs/config/valve.html -->
- <Valve className="org.apache.catalina.valves.FastCommonAccessLogValve" directory="logs"
- prefix="access_log." suffix=".txt" pattern="common" resolveHosts="false"/>
-
- </Host>
- </Engine>
- </Service>
-</Server>
diff --git a/client/tomcatconf/server7-nonssl.xml.in b/client/tomcatconf/server7-nonssl.xml.in
deleted file mode 100755
index 6e6a7b28bc9..00000000000
--- a/client/tomcatconf/server7-nonssl.xml.in
+++ /dev/null
@@ -1,149 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- Note: A "Server" is not itself a "Container", so you may not
- define subcomponents such as "Valves" at this level.
- Documentation at /docs/config/server.html
- -->
-<Server port="8005" shutdown="SHUTDOWN">
-
- <!--APR library loader. Documentation at /docs/apr.html -->
- <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
- <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
- <Listener className="org.apache.catalina.core.JasperListener" />
- <!-- JMX Support for the Tomcat server. Documentation at /docs/non-existent.html -->
- <!-- Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" / -->
- <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
-
- <!-- Global JNDI resources
- Documentation at /docs/jndi-resources-howto.html
- -->
- <GlobalNamingResources>
- <!-- Editable user database that can also be used by
- UserDatabaseRealm to authenticate users
- -->
- <Resource name="UserDatabase" auth="Container"
- type="org.apache.catalina.UserDatabase"
- description="User database that can be updated and saved"
- factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
- pathname="conf/tomcat-users.xml" />
- </GlobalNamingResources>
-
- <!-- A "Service" is a collection of one or more "Connectors" that share
- a single "Container" Note: A "Service" is not itself a "Container",
- so you may not define subcomponents such as "Valves" at this level.
- Documentation at /docs/config/service.html
- -->
- <Service name="Catalina">
-
- <!--The connectors can use a shared executor, you can define one or more named thread pools-->
- <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
- maxThreads="150" minSpareThreads="25"/>
-
-
- <!-- A "Connector" represents an endpoint by which requests are received
- and responses are returned. Documentation at :
- Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
- Java AJP Connector: /docs/config/ajp.html
- APR (HTTP/AJP) Connector: /docs/apr.html
- Define a non-SSL HTTP/1.1 Connector on port 8080
- -->
- <!--
- <Connector port="8080" protocol="HTTP/1.1"
- connectionTimeout="20000"
- redirectPort="8443" />
- -->
- <!-- A "Connector" using the shared thread pool-->
- <Connector executor="tomcatThreadPool" URIEncoding="UTF-8"
- port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
- connectionTimeout="20000" disableUploadTimeout="true"
- acceptCount="150" enableLookups="false" maxThreads="150"
- maxHttpHeaderSize="8192" redirectPort="8443" />
-
-
- <!-- Define a SSL HTTP/1.1 Connector on port 8443
- This connector uses the JSSE configuration, when using APR, the
- connector should be using the OpenSSL style configuration
- described in the APR documentation -->
- <!--
- <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
- maxThreads="150" scheme="https" secure="true"
- clientAuth="false" sslProtocol="TLS" sslEnabledProtocols="TLSv1.2,TLSv1.1"
- keystoreType="PKCS12"
- keystoreFile="conf/cloud-localhost.pk12"
- keystorePass="password"
- />
- -->
-
- <!-- Define an AJP 1.3 Connector on port 20400 -->
- <Connector port="20400" protocol="AJP/1.3" redirectPort="8443" />
-
-
- <!-- An Engine represents the entry point (within Catalina) that processes
- every request. The Engine implementation for Tomcat stand alone
- analyzes the HTTP headers included with the request, and passes them
- on to the appropriate Host (virtual host).
- Documentation at /docs/config/engine.html -->
-
- <!-- You should set jvmRoute to support load-balancing via AJP ie :
- <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
- -->
- <Engine name="Catalina" defaultHost="localhost">
-
- <!--For clustering, please take a look at documentation at:
- /docs/cluster-howto.html (simple how to)
- /docs/config/cluster.html (reference documentation) -->
- <!--
- <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
- -->
-
- <!-- The request dumper valve dumps useful debugging information about
- the request and response data received and sent by Tomcat.
- Documentation at: /docs/config/valve.html -->
- <!--
- <Valve className="org.apache.catalina.valves.RequestDumperValve"/>
- -->
-
- <!-- This Realm uses the UserDatabase configured in the global JNDI
- resources under the key "UserDatabase". Any edits
- that are performed against this UserDatabase are immediately
- available for use by the Realm. -->
- <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
- resourceName="UserDatabase"/>
-
- <!-- Define the default virtual host
- Note: XML Schema validation will not work with Xerces 2.2.
- -->
- <Host name="localhost" appBase="webapps"
- unpackWARs="true" autoDeploy="true"
- xmlValidation="false" xmlNamespaceAware="false">
-
- <!-- SingleSignOn valve, share authentication between web applications
- Documentation at: /docs/config/valve.html -->
- <!--
- <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
- -->
-
- <!-- Access log processes all example.
- Documentation at: /docs/config/valve.html -->
- <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
- prefix="access_log." suffix=".txt" pattern="common" resolveHosts="false"/>
-
- </Host>
- </Engine>
- </Service>
-</Server>
diff --git a/client/tomcatconf/server7-ssl.xml.in b/client/tomcatconf/server7-ssl.xml.in
deleted file mode 100755
index 2633bcad760..00000000000
--- a/client/tomcatconf/server7-ssl.xml.in
+++ /dev/null
@@ -1,157 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- Note: A "Server" is not itself a "Container", so you may not
- define subcomponents such as "Valves" at this level.
- Documentation at /docs/config/server.html
- -->
-<Server port="8005" shutdown="SHUTDOWN">
-
- <!--APR library loader. Documentation at /docs/apr.html -->
- <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
- <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
- <Listener className="org.apache.catalina.core.JasperListener" />
- <!-- JMX Support for the Tomcat server. Documentation at /docs/non-existent.html -->
- <!-- Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" /-->
- <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
-
- <!-- Global JNDI resources
- Documentation at /docs/jndi-resources-howto.html
- -->
- <GlobalNamingResources>
- <!-- Editable user database that can also be used by
- UserDatabaseRealm to authenticate users
- -->
- <Resource name="UserDatabase" auth="Container"
- type="org.apache.catalina.UserDatabase"
- description="User database that can be updated and saved"
- factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
- pathname="conf/tomcat-users.xml" />
- </GlobalNamingResources>
-
- <!-- A "Service" is a collection of one or more "Connectors" that share
- a single "Container" Note: A "Service" is not itself a "Container",
- so you may not define subcomponents such as "Valves" at this level.
- Documentation at /docs/config/service.html
- -->
- <Service name="Catalina">
-
- <!--The connectors can use a shared executor, you can define one or more named thread pools-->
- <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
- maxThreads="150" minSpareThreads="25"/>
-
-
- <!-- A "Connector" represents an endpoint by which requests are received
- and responses are returned. Documentation at :
- Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
- Java AJP Connector: /docs/config/ajp.html
- APR (HTTP/AJP) Connector: /docs/apr.html
- Define a non-SSL HTTP/1.1 Connector on port 8080
- -->
- <!--
- <Connector port="8080" protocol="HTTP/1.1"
- connectionTimeout="20000"
- redirectPort="8443" />
- -->
- <!-- A "Connector" using the shared thread pool-->
- <!--
- <Connector executor="tomcatThreadPool"
- port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
- connectionTimeout="20000" disableUploadTimeout="true"
- acceptCount="150" enableLookups="false" maxThreads="150"
- maxHttpHeaderSize="8192" redirectPort="8443" />
- -->
- <!-- Define a SSL HTTP/1.1 Connector on port 8443
- This connector uses the JSSE configuration, when using APR, the
- connector should be using the OpenSSL style configuration
- described in the APR documentation -->
- <!--
- <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
- maxThreads="150" scheme="https" secure="true"
- clientAuth="false" sslProtocol="TLS" sslEnabledProtocols="TLSv1.2,TLSv1.1"
- keystoreType="PKCS12"
- keystoreFile="conf/cloud-localhost.pk12"
- keystorePass="password"
- />
- -->
-
- <!-- Listen on 6443 instead of 8443 because tomcat6 will change 8443 to a random one when CATALINA_HOME is not /usr/share/tomcat6 -->
- <Connector port="6443" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true"
- maxThreads="150" scheme="https" secure="true" URIEncoding="UTF-8"
- clientAuth="false" sslProtocol="TLS"
- keystoreType="JKS"
- keystoreFile="/etc/cloudstack/management/cloudmanagementserver.keystore"
- keystorePass="vmops.com"/>
-
- <!-- Define an AJP 1.3 Connector on port 20400 -->
- <Connector port="20400" protocol="AJP/1.3" redirectPort="6443" />
-
-
- <!-- An Engine represents the entry point (within Catalina) that processes
- every request. The Engine implementation for Tomcat stand alone
- analyzes the HTTP headers included with the request, and passes them
- on to the appropriate Host (virtual host).
- Documentation at /docs/config/engine.html -->
-
- <!-- You should set jvmRoute to support load-balancing via AJP ie :
- <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
- -->
- <Engine name="Catalina" defaultHost="localhost">
-
- <!--For clustering, please take a look at documentation at:
- /docs/cluster-howto.html (simple how to)
- /docs/config/cluster.html (reference documentation) -->
- <!--
- <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
- -->
-
- <!-- The request dumper valve dumps useful debugging information about
- the request and response data received and sent by Tomcat.
- Documentation at: /docs/config/valve.html -->
- <!--
- <Valve className="org.apache.catalina.valves.RequestDumperValve"/>
- -->
-
- <!-- This Realm uses the UserDatabase configured in the global JNDI
- resources under the key "UserDatabase". Any edits
- that are performed against this UserDatabase are immediately
- available for use by the Realm. -->
- <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
- resourceName="UserDatabase"/>
-
- <!-- Define the default virtual host
- Note: XML Schema validation will not work with Xerces 2.2.
- -->
- <Host name="localhost" appBase="webapps"
- unpackWARs="true" autoDeploy="true"
- xmlValidation="false" xmlNamespaceAware="false">
-
- <!-- SingleSignOn valve, share authentication between web applications
- Documentation at: /docs/config/valve.html -->
- <!--
- <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
- -->
-
- <!-- Access log processes all example.
- Documentation at: /docs/config/valve.html -->
- <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
- prefix="access_log." suffix=".txt" pattern="common" resolveHosts="false"/>
-
- </Host>
- </Engine>
- </Service>
-</Server>
diff --git a/client/tomcatconf/tomcat-users.xml.in b/client/tomcatconf/tomcat-users.xml.in
deleted file mode 100644
index 81422a02892..00000000000
--- a/client/tomcatconf/tomcat-users.xml.in
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<tomcat-users>
-<!--
- <role rolename="tomcat"/>
- <role rolename="role1"/>
- <user username="tomcat" password="tomcat" roles="tomcat"/>
- <user username="both" password="tomcat" roles="tomcat,role1"/>
- <user username="role1" password="tomcat" roles="role1"/>
--->
-
-<!-- The host manager webapp is restricted to users with role "admin" -->
-<!--<user name="tomcat" password="password" roles="admin" />-->
-<!-- The manager webapp is restricted to users with role "manager" -->
-<!--<user name="tomcat" password="password" roles="manager" />-->
-</tomcat-users>
diff --git a/client/tomcatconf/tomcat6-nonssl.conf.in b/client/tomcatconf/tomcat6-nonssl.conf.in
deleted file mode 100644
index 3f08c906660..00000000000
--- a/client/tomcatconf/tomcat6-nonssl.conf.in
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/env bash
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-
-# System-wide configuration file for tomcat6 services
-# This will be sourced by tomcat6 and any secondary service
-# Values will be overridden by service-specific configuration
-# files in /etc/sysconfig
-#
-# Use this one to change default values for all services
-# Change the service specific ones to affect only one service
-# (see, for instance, /etc/sysconfig/tomcat6)
-#
-
-# Where your java installation lives
-#JAVA_HOME="/usr/lib/jvm/java"
-
-# Where your tomcat installation lives
-CATALINA_BASE="@MSENVIRON@"
-CATALINA_HOME="@MSENVIRON@"
-JASPER_HOME="@MSENVIRON@"
-CATALINA_TMPDIR="@MSENVIRON@/temp"
-
-# You can pass some parameters to java here if you wish to
-#JAVA_OPTS="-Xminf0.1 -Xmaxf0.3"
-
-# Use JAVA_OPTS to set java.library.path for libtcnative.so
-#JAVA_OPTS="-Djava.library.path=/usr/lib64"
-JAVA_OPTS="-Djava.awt.headless=true -Dcom.sun.management.jmxremote=false -Xmx2g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=@MSLOGDIR@ -XX:PermSize=512M -XX:MaxPermSize=800m -Djava.security.properties=/etc/cloudstack/management/java.security.ciphers"
-
-# What user should run tomcat
-TOMCAT_USER="@MSUSER@"
-# Do not remove the following line
-TOMCAT6_USER="$TOMCAT_USER"
-
-TOMCAT_LOG="@MSLOGDIR@/catalina.out"
-
-# You can change your tomcat locale here
-#LANG="en_US"
-
-# Run tomcat under the Java Security Manager
-SECURITY_MANAGER="false"
-
-# Time to wait in seconds, before killing process
-SHUTDOWN_WAIT="30"
-
-# Whether to annoy the user with "attempting to shut down" messages or not
-SHUTDOWN_VERBOSE="false"
-
-# Set the TOMCAT_PID location
-CATALINA_PID="@PIDDIR@/@PACKAGE@-management.pid"
-
-# Connector port is 8080 for this tomcat6 instance
-#CONNECTOR_PORT="8080"
-
-# We pick up the classpath in the next line
-
-dummy=1 ; . @MSCONF@/classpath.conf
diff --git a/client/tomcatconf/tomcat6-ssl.conf.in b/client/tomcatconf/tomcat6-ssl.conf.in
deleted file mode 100644
index e7c53ac9f8f..00000000000
--- a/client/tomcatconf/tomcat6-ssl.conf.in
+++ /dev/null
@@ -1,72 +0,0 @@
-#!/usr/bin/env bash
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# System-wide configuration file for tomcat6 services
-# This will be sourced by tomcat6 and any secondary service
-# Values will be overridden by service-specific configuration
-# files in /etc/sysconfig
-#
-# Use this one to change default values for all services
-# Change the service specific ones to affect only one service
-# (see, for instance, /etc/sysconfig/tomcat6)
-#
-
-# Where your java installation lives
-#JAVA_HOME="/usr/lib/jvm/java"
-
-# Where your tomcat installation lives
-CATALINA_BASE="@MSENVIRON@"
-CATALINA_HOME="@MSENVIRON@"
-JASPER_HOME="@MSENVIRON@"
-CATALINA_TMPDIR="@MSENVIRON@/temp"
-
-# You can pass some parameters to java here if you wish to
-#JAVA_OPTS="-Xminf0.1 -Xmaxf0.3"
-
-# Use JAVA_OPTS to set java.library.path for libtcnative.so
-#JAVA_OPTS="-Djava.library.path=/usr/lib64"
-JAVA_OPTS="-Djava.awt.headless=true -Dcom.sun.management.jmxremote=false -Djavax.net.ssl.trustStore=/etc/cloudstack/management/cloudmanagementserver.keystore -Djavax.net.ssl.trustStorePassword=vmops.com -Xmx2g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=@MSLOGDIR@ -XX:MaxPermSize=800m -XX:PermSize=512M -Djava.security.properties=/etc/cloudstack/management/java.security.ciphers"
-
-# What user should run tomcat
-TOMCAT_USER="@MSUSER@"
-# Do not remove the following line
-TOMCAT6_USER="$TOMCAT_USER"
-
-TOMCAT_LOG="@MSLOGDIR@/catalina.out"
-
-# You can change your tomcat locale here
-#LANG="en_US"
-
-# Run tomcat under the Java Security Manager
-SECURITY_MANAGER="false"
-
-# Time to wait in seconds, before killing process
-SHUTDOWN_WAIT="30"
-
-# Whether to annoy the user with "attempting to shut down" messages or not
-SHUTDOWN_VERBOSE="false"
-
-# Set the TOMCAT_PID location
-CATALINA_PID="@PIDDIR@/@PACKAGE@-management.pid"
-
-# Connector port is 8080 for this tomcat6 instance
-#CONNECTOR_PORT="8080"
-
-# We pick up the classpath in the next line
-
-dummy=1 ; . @MSCONF@/classpath.conf
diff --git a/client/tomcatconf/web.xml.in b/client/tomcatconf/web.xml.in
deleted file mode 100644
index 8645a64da42..00000000000
--- a/client/tomcatconf/web.xml.in
+++ /dev/null
@@ -1,1187 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<web-app xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
- version="2.5">
-
- <!-- ======================== Introduction ============================== -->
- <!-- This document defines default values for *all* web applications -->
- <!-- loaded into this instance of Tomcat. As each application is -->
- <!-- deployed, this file is processed, followed by the -->
- <!-- "/WEB-INF/web.xml" deployment descriptor from your own -->
- <!-- applications. -->
- <!-- -->
- <!-- WARNING: Do not configure application-specific resources here! -->
- <!-- They should go in the "/WEB-INF/web.xml" file in your application. -->
-
-
- <!-- ================== Built In Servlet Definitions ==================== -->
-
-
- <!-- The default servlet for all web applications, that serves static -->
- <!-- resources. It processes all requests that are not mapped to other -->
- <!-- servlets with servlet mappings (defined either here or in your own -->
- <!-- web.xml file. This servlet supports the following initialization -->
- <!-- parameters (default values are in square brackets): -->
- <!-- -->
- <!-- debug Debugging detail level for messages logged -->
- <!-- by this servlet. [0] -->
- <!-- -->
- <!-- fileEncoding Encoding to be used to read static resources -->
- <!-- [platform default] -->
- <!-- -->
- <!-- input Input buffer size (in bytes) when reading -->
- <!-- resources to be served. [2048] -->
- <!-- -->
- <!-- listings Should directory listings be produced if there -->
- <!-- is no welcome file in this directory? [false] -->
- <!-- WARNING: Listings for directories with many -->
- <!-- entries can be slow and may consume -->
- <!-- significant proportions of server resources. -->
- <!-- -->
- <!-- output Output buffer size (in bytes) when writing -->
- <!-- resources to be served. [2048] -->
- <!-- -->
- <!-- readonly Is this context "read only", so HTTP -->
- <!-- commands like PUT and DELETE are -->
- <!-- rejected? [true] -->
- <!-- -->
- <!-- readmeFile File name to display with the directory -->
- <!-- contents. [null] -->
- <!-- -->
- <!-- sendfileSize If the connector used supports sendfile, this -->
- <!-- represents the minimal file size in KB for -->
- <!-- which sendfile will be used. Use a negative -->
- <!-- value to always disable sendfile. [48] -->
- <!-- -->
- <!-- useAcceptRanges Should the Accept-Ranges header be included -->
- <!-- in responses where appropriate? [true] -->
- <!-- -->
- <!-- For directory listing customization. Checks localXsltFile, then -->
- <!-- globalXsltFile, then defaults to original behavior. -->
- <!-- -->
- <!-- localXsltFile Make directory listings an XML doc and -->
- <!-- pass the result to this style sheet residing -->
- <!-- in that directory. This overrides -->
- <!-- globalXsltFile[null] -->
- <!-- -->
- <!-- globalXsltFile Site wide configuration version of -->
- <!-- localXsltFile This argument is expected -->
- <!-- to be a physical file. [null] -->
- <!-- -->
- <!-- -->
-
- <servlet>
- <servlet-name>default</servlet-name>
- <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
- <init-param>
- <param-name>debug</param-name>
- <param-value>0</param-value>
- </init-param>
- <init-param>
- <param-name>listings</param-name>
- <param-value>false</param-value>
- </init-param>
- <load-on-startup>1</load-on-startup>
- </servlet>
-
-
- <!-- This servlet has been deprecated due to security concerns. Servlets -->
- <!-- should be explicitly mapped in web.xml -->
- <!-- -->
- <!-- The "invoker" servlet, which executes anonymous servlet classes -->
- <!-- that have not been defined in a web.xml file. Traditionally, this -->
- <!-- servlet is mapped to the URL pattern "/servlet/*", but you can map -->
- <!-- it to other patterns as well. The extra path info portion of such a -->
- <!-- request must be the fully qualified class name of a Java class that -->
- <!-- implements Servlet (or extends HttpServlet), or the servlet name -->
- <!-- of an existing servlet definition. This servlet supports the -->
- <!-- following initialization parameters (default values are in square -->
- <!-- brackets): -->
- <!-- -->
- <!-- debug Debugging detail level for messages logged -->
- <!-- by this servlet. [0] -->
-
-<!--
- <servlet>
- <servlet-name>invoker</servlet-name>
- <servlet-class>
- org.apache.catalina.servlets.InvokerServlet
- </servlet-class>
- <init-param>
- <param-name>debug</param-name>
- <param-value>0</param-value>
- </init-param>
- <load-on-startup>2</load-on-startup>
- </servlet>
--->
-
-
- <!-- The JSP page compiler and execution servlet, which is the mechanism -->
- <!-- used by Tomcat to support JSP pages. Traditionally, this servlet -->
- <!-- is mapped to the URL pattern "*.jsp". This servlet supports the -->
- <!-- following initialization parameters (default values are in square -->
- <!-- brackets): -->
- <!-- -->
- <!-- checkInterval If development is false and checkInterval is -->
- <!-- greater than zero, background compilations are -->
- <!-- enabled. checkInterval is the time in seconds -->
- <!-- between checks to see if a JSP page (and its -->
- <!-- dependent files) needs to be recompiled. [0] -->
- <!-- -->
- <!-- classdebuginfo Should the class file be compiled with -->
- <!-- debugging information? [true] -->
- <!-- -->
- <!-- classpath What class path should I use while compiling -->
- <!-- generated servlets? [Created dynamically -->
- <!-- based on the current web application] -->
- <!-- -->
- <!-- compiler Which compiler Ant should use to compile JSP -->
- <!-- pages. See the jasper documentation for more -->
- <!-- information. -->
- <!-- -->
- <!-- compilerSourceVM Compiler source VM. [1.5] -->
- <!-- -->
- <!-- compilerTargetVM Compiler target VM. [1.5] -->
- <!-- -->
- <!-- development Is Jasper used in development mode? If true, -->
- <!-- the frequency at which JSPs are checked for -->
- <!-- modification may be specified via the -->
- <!-- modificationTestInterval parameter. [true] -->
- <!-- -->
- <!-- displaySourceFragment -->
- <!-- Should a source fragment be included in -->
- <!-- exception messages? [true] -->
- <!-- -->
- <!-- dumpSmap Should the SMAP info for JSR45 debugging be -->
- <!-- dumped to a file? [false] -->
- <!-- False if suppressSmap is true -->
- <!-- -->
- <!-- enablePooling Determines whether tag handler pooling is -->
- <!-- enabled. This is a compilation option. It will -->
- <!-- not alter the behaviour of JSPs that have -->
- <!-- already been compiled. [true] -->
- <!-- -->
- <!-- engineOptionsClass Allows specifying the Options class used to -->
- <!-- configure Jasper. If not present, the default -->
- <!-- EmbeddedServletOptions will be used. -->
- <!-- -->
- <!-- errorOnUseBeanInvalidClassAttribute -->
- <!-- Should Jasper issue an error when the value of -->
- <!-- the class attribute in an useBean action is -->
- <!-- not a valid bean class? [true] -->
- <!-- -->
- <!-- fork Tell Ant to fork compiles of JSP pages so that -->
- <!-- a separate JVM is used for JSP page compiles -->
- <!-- from the one Tomcat is running in. [true] -->
- <!-- -->
- <!-- genStrAsCharArray Should text strings be generated as char -->
- <!-- arrays, to improve performance in some cases? -->
- <!-- [false] -->
- <!-- -->
- <!-- ieClassId The class-id value to be sent to Internet -->
- <!-- Explorer when using <jsp:plugin> tags. -->
- <!-- [clsid:8AD9C840-044E-11D1-B3E9-00805F499D93] -->
- <!-- -->
- <!-- javaEncoding Java file encoding to use for generating java -->
- <!-- source files. [UTF8] -->
- <!-- -->
- <!-- keepgenerated Should we keep the generated Java source code -->
- <!-- for each page instead of deleting it? [true] -->
- <!-- -->
- <!-- mappedfile Should we generate static content with one -->
- <!-- print statement per input line, to ease -->
- <!-- debugging? [true] -->
- <!-- -->
- <!-- modificationTestInterval -->
- <!-- Causes a JSP (and its dependent files) to not -->
- <!-- be checked for modification during the -->
- <!-- specified time interval (in seconds) from the -->
- <!-- last time the JSP was checked for -->
- <!-- modification. A value of 0 will cause the JSP -->
- <!-- to be checked on every access. -->
- <!-- Used in development mode only. [4] -->
- <!-- -->
- <!-- scratchdir What scratch directory should we use when -->
- <!-- compiling JSP pages? [default work directory -->
- <!-- for the current web application] -->
- <!-- -->
- <!-- suppressSmap Should the generation of SMAP info for JSR45 -->
- <!-- debugging be suppressed? [false] -->
- <!-- -->
- <!-- trimSpaces Should white spaces in template text between -->
- <!-- actions or directives be trimmed? [false] -->
- <!-- -->
- <!-- xpoweredBy Determines whether X-Powered-By response -->
- <!-- header is added by generated servlet [false] -->
- <!-- -->
- <!-- If you wish to use Jikes to compile JSP pages: -->
- <!-- Please see the "Using Jikes" section of the Jasper-HowTo -->
- <!-- page in the Tomcat documentation. -->
-
- <servlet>
- <servlet-name>jsp</servlet-name>
- <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
- <init-param>
- <param-name>fork</param-name>
- <param-value>false</param-value>
- </init-param>
- <init-param>
- <param-name>xpoweredBy</param-name>
- <param-value>false</param-value>
- </init-param>
- <load-on-startup>3</load-on-startup>
- </servlet>
-
-
- <!-- NOTE: An SSI Filter is also available as an alternative SSI -->
- <!-- implementation. Use either the Servlet or the Filter but NOT both. -->
- <!-- -->
- <!-- Server Side Includes processing servlet, which processes SSI -->
- <!-- directives in HTML pages consistent with similar support in web -->
- <!-- servers like Apache. Traditionally, this servlet is mapped to the -->
- <!-- URL pattern "*.shtml". This servlet supports the following -->
- <!-- initialization parameters (default values are in square brackets): -->
- <!-- -->
- <!-- buffered Should output from this servlet be buffered? -->
- <!-- (0=false, 1=true) [0] -->
- <!-- -->
- <!-- debug Debugging detail level for messages logged -->
- <!-- by this servlet. [0] -->
- <!-- -->
- <!-- expires The number of seconds before a page with SSI -->
- <!-- directives will expire. [No default] -->
- <!-- -->
- <!-- isVirtualWebappRelative -->
- <!-- Should "virtual" paths be interpreted as -->
- <!-- relative to the context root, instead of -->
- <!-- the server root? (0=false, 1=true) [0] -->
- <!-- -->
- <!-- inputEncoding The encoding to assume for SSI resources if -->
- <!-- one is not available from the resource. -->
- <!-- [Platform default] -->
- <!-- -->
- <!-- outputEncoding The encoding to use for the page that results -->
- <!-- from the SSI processing. [UTF-8] -->
-
-<!--
- <servlet>
- <servlet-name>ssi</servlet-name>
- <servlet-class>
- org.apache.catalina.ssi.SSIServlet
- </servlet-class>
- <init-param>
- <param-name>buffered</param-name>
- <param-value>1</param-value>
- </init-param>
- <init-param>
- <param-name>debug</param-name>
- <param-value>0</param-value>
- </init-param>
- <init-param>
- <param-name>expires</param-name>
- <param-value>666</param-value>
- </init-param>
- <init-param>
- <param-name>isVirtualWebappRelative</param-name>
- <param-value>0</param-value>
- </init-param>
- <load-on-startup>4</load-on-startup>
- </servlet>
--->
-
-
- <!-- Common Gateway Includes (CGI) processing servlet, which supports -->
- <!-- execution of external applications that conform to the CGI spec -->
- <!-- requirements. Typically, this servlet is mapped to the URL pattern -->
- <!-- "/cgi-bin/*", which means that any CGI applications that are -->
- <!-- executed must be present within the web application. This servlet -->
- <!-- supports the following initialization parameters (default values -->
- <!-- are in square brackets): -->
- <!-- -->
- <!-- cgiPathPrefix The CGI search path will start at -->
- <!-- webAppRootDir + File.separator + this prefix. -->
- <!-- [WEB-INF/cgi] -->
- <!-- -->
- <!-- debug Debugging detail level for messages logged -->
- <!-- by this servlet. [0] -->
- <!-- -->
- <!-- executable Name of the executable used to run the -->
- <!-- script. [perl] -->
- <!-- -->
- <!-- parameterEncoding Name of parameter encoding to be used with -->
- <!-- CGI servlet. -->
- <!-- [System.getProperty("file.encoding","UTF-8")] -->
- <!-- -->
- <!-- passShellEnvironment Should the shell environment variables (if -->
- <!-- any) be passed to the CGI script? [false] -->
- <!-- -->
- <!-- stderrTimeout The time (in milliseconds) to wait for the -->
- <!-- reading of stderr to complete before -->
- <!-- terminating the CGI process. [2000] -->
-
-<!--
- <servlet>
- <servlet-name>cgi</servlet-name>
- <servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class>
- <init-param>
- <param-name>debug</param-name>
- <param-value>0</param-value>
- </init-param>
- <init-param>
- <param-name>cgiPathPrefix</param-name>
- <param-value>WEB-INF/cgi</param-value>
- </init-param>
- <load-on-startup>5</load-on-startup>
- </servlet>
--->
-
-
- <!-- ================ Built In Servlet Mappings ========================= -->
-
-
- <!-- The servlet mappings for the built in servlets defined above. Note -->
- <!-- that, by default, the CGI and SSI servlets are *not* mapped. You -->
- <!-- must uncomment these mappings (or add them to your application's own -->
- <!-- web.xml deployment descriptor) to enable these services -->
-
- <!-- The mapping for the default servlet -->
- <servlet-mapping>
- <servlet-name>default</servlet-name>
- <url-pattern>/</url-pattern>
- </servlet-mapping>
-
- <!-- The mapping for the deprecated invoker servlet -->
-<!--
- <servlet-mapping>
- <servlet-name>invoker</servlet-name>
- <url-pattern>/servlet/*</url-pattern>
- </servlet-mapping>
--->
-
- <!-- The mapping for the JSP servlet -->
- <servlet-mapping>
- <servlet-name>jsp</servlet-name>
- <url-pattern>*.jsp</url-pattern>
- </servlet-mapping>
-
- <servlet-mapping>
- <servlet-name>jsp</servlet-name>
- <url-pattern>*.jspx</url-pattern>
- </servlet-mapping>
-
- <!-- The mapping for the SSI servlet -->
-<!--
- <servlet-mapping>
- <servlet-name>ssi</servlet-name>
- <url-pattern>*.shtml</url-pattern>
- </servlet-mapping>
--->
-
- <!-- The mapping for the CGI Gateway servlet -->
-
-<!--
- <servlet-mapping>
- <servlet-name>cgi</servlet-name>
- <url-pattern>/cgi-bin/*</url-pattern>
- </servlet-mapping>
--->
-
-
- <!-- ================== Built In Filter Definitions ===================== -->
-
- <!-- NOTE: An SSI Servlet is also available as an alternative SSI -->
- <!-- implementation. Use either the Servlet or the Filter but NOT both. -->
- <!-- -->
- <!-- Server Side Includes processing filter, which processes SSI -->
- <!-- directives in HTML pages consistent with similar support in web -->
- <!-- servers like Apache. Traditionally, this filter is mapped to the -->
- <!-- URL pattern "*.shtml", though it can be mapped to "*" as it will -->
- <!-- selectively enable/disable SSI processing based on mime types. For -->
- <!-- this to work you will need to uncomment the .shtml mime type -->
- <!-- definition towards the bottom of this file. -->
- <!-- The contentType init param allows you to apply SSI processing to JSP -->
- <!-- pages, javascript, or any other content you wish. This filter -->
- <!-- supports the following initialization parameters (default values are -->
- <!-- in square brackets): -->
- <!-- -->
- <!-- contentType A regex pattern that must be matched before -->
- <!-- SSI processing is applied. -->
- <!-- [text/x-server-parsed-html(;.*)?] -->
- <!-- -->
- <!-- debug Debugging detail level for messages logged -->
- <!-- by this servlet. [0] -->
- <!-- -->
- <!-- expires The number of seconds before a page with SSI -->
- <!-- directives will expire. [No default] -->
- <!-- -->
- <!-- isVirtualWebappRelative -->
- <!-- Should "virtual" paths be interpreted as -->
- <!-- relative to the context root, instead of -->
- <!-- the server root? (0=false, 1=true) [0] -->
-
-<!--
- <filter>
- <filter-name>ssi</filter-name>
- <filter-class>
- org.apache.catalina.ssi.SSIFilter
- </filter-class>
- <init-param>
- <param-name>contentType</param-name>
- <param-value>text/x-server-parsed-html(;.*)?</param-value>
- </init-param>
- <init-param>
- <param-name>debug</param-name>
- <param-value>0</param-value>
- </init-param>
- <init-param>
- <param-name>expires</param-name>
- <param-value>666</param-value>
- </init-param>
- <init-param>
- <param-name>isVirtualWebappRelative</param-name>
- <param-value>0</param-value>
- </init-param>
- </filter>
--->
-
-
- <!-- ==================== Built In Filter Mappings ====================== -->
-
- <!-- The mapping for the SSI Filter -->
-<!--
- <filter-mapping>
- <filter-name>ssi</filter-name>
- <url-pattern>*.shtml</url-pattern>
- </filter-mapping>
--->
-
-
- <!-- ==================== Default Session Configuration ================= -->
- <!-- You can set the default session timeout (in minutes) for all newly -->
- <!-- created sessions by modifying the value below. -->
-
- <session-config>
- <session-timeout>30</session-timeout>
- </session-config>
-
-
- <!-- ===================== Default MIME Type Mappings =================== -->
- <!-- When serving static resources, Tomcat will automatically generate -->
- <!-- a "Content-Type" header based on the resource's filename extension, -->
- <!-- based on these mappings. Additional mappings can be added here (to -->
- <!-- apply to all web applications), or in your own application's web.xml -->
- <!-- deployment descriptor. -->
-
- <mime-mapping>
- <extension>abs</extension>
- <mime-type>audio/x-mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ai</extension>
- <mime-type>application/postscript</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>aif</extension>
- <mime-type>audio/x-aiff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>aifc</extension>
- <mime-type>audio/x-aiff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>aiff</extension>
- <mime-type>audio/x-aiff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>aim</extension>
- <mime-type>application/x-aim</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>art</extension>
- <mime-type>image/x-jg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>asf</extension>
- <mime-type>video/x-ms-asf</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>asx</extension>
- <mime-type>video/x-ms-asf</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>au</extension>
- <mime-type>audio/basic</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>avi</extension>
- <mime-type>video/x-msvideo</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>avx</extension>
- <mime-type>video/x-rad-screenplay</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>bcpio</extension>
- <mime-type>application/x-bcpio</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>bin</extension>
- <mime-type>application/octet-stream</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>bmp</extension>
- <mime-type>image/bmp</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>body</extension>
- <mime-type>text/html</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>cdf</extension>
- <mime-type>application/x-cdf</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>cer</extension>
- <mime-type>application/x-x509-ca-cert</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>class</extension>
- <mime-type>application/java</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>cpio</extension>
- <mime-type>application/x-cpio</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>csh</extension>
- <mime-type>application/x-csh</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>css</extension>
- <mime-type>text/css</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>dib</extension>
- <mime-type>image/bmp</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>doc</extension>
- <mime-type>application/msword</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>dtd</extension>
- <mime-type>application/xml-dtd</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>dv</extension>
- <mime-type>video/x-dv</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>dvi</extension>
- <mime-type>application/x-dvi</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>eps</extension>
- <mime-type>application/postscript</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>etx</extension>
- <mime-type>text/x-setext</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>exe</extension>
- <mime-type>application/octet-stream</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>gif</extension>
- <mime-type>image/gif</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>gtar</extension>
- <mime-type>application/x-gtar</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>gz</extension>
- <mime-type>application/x-gzip</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>hdf</extension>
- <mime-type>application/x-hdf</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>hqx</extension>
- <mime-type>application/mac-binhex40</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>htc</extension>
- <mime-type>text/x-component</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>htm</extension>
- <mime-type>text/html</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>html</extension>
- <mime-type>text/html</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>hqx</extension>
- <mime-type>application/mac-binhex40</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ief</extension>
- <mime-type>image/ief</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jad</extension>
- <mime-type>text/vnd.sun.j2me.app-descriptor</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jar</extension>
- <mime-type>application/java-archive</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>java</extension>
- <mime-type>text/plain</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jnlp</extension>
- <mime-type>application/x-java-jnlp-file</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jpe</extension>
- <mime-type>image/jpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jpeg</extension>
- <mime-type>image/jpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jpg</extension>
- <mime-type>image/jpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>js</extension>
- <mime-type>text/javascript</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jsf</extension>
- <mime-type>text/plain</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jspf</extension>
- <mime-type>text/plain</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>kar</extension>
- <mime-type>audio/x-midi</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>latex</extension>
- <mime-type>application/x-latex</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>m3u</extension>
- <mime-type>audio/x-mpegurl</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mac</extension>
- <mime-type>image/x-macpaint</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>man</extension>
- <mime-type>application/x-troff-man</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mathml</extension>
- <mime-type>application/mathml+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>me</extension>
- <mime-type>application/x-troff-me</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mid</extension>
- <mime-type>audio/x-midi</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>midi</extension>
- <mime-type>audio/x-midi</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mif</extension>
- <mime-type>application/x-mif</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mov</extension>
- <mime-type>video/quicktime</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>movie</extension>
- <mime-type>video/x-sgi-movie</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mp1</extension>
- <mime-type>audio/x-mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mp2</extension>
- <mime-type>audio/x-mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mp3</extension>
- <mime-type>audio/x-mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mp4</extension>
- <mime-type>video/mp4</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mpa</extension>
- <mime-type>audio/x-mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mpe</extension>
- <mime-type>video/mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mpeg</extension>
- <mime-type>video/mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mpega</extension>
- <mime-type>audio/x-mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mpg</extension>
- <mime-type>video/mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mpv2</extension>
- <mime-type>video/mpeg2</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ms</extension>
- <mime-type>application/x-wais-source</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>nc</extension>
- <mime-type>application/x-netcdf</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>oda</extension>
- <mime-type>application/oda</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Database -->
- <extension>odb</extension>
- <mime-type>application/vnd.oasis.opendocument.database</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Chart -->
- <extension>odc</extension>
- <mime-type>application/vnd.oasis.opendocument.chart</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Formula -->
- <extension>odf</extension>
- <mime-type>application/vnd.oasis.opendocument.formula</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Drawing -->
- <extension>odg</extension>
- <mime-type>application/vnd.oasis.opendocument.graphics</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Image -->
- <extension>odi</extension>
- <mime-type>application/vnd.oasis.opendocument.image</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Master Document -->
- <extension>odm</extension>
- <mime-type>application/vnd.oasis.opendocument.text-master</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Presentation -->
- <extension>odp</extension>
- <mime-type>application/vnd.oasis.opendocument.presentation</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Spreadsheet -->
- <extension>ods</extension>
- <mime-type>application/vnd.oasis.opendocument.spreadsheet</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Text -->
- <extension>odt</extension>
- <mime-type>application/vnd.oasis.opendocument.text</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ogg</extension>
- <mime-type>application/ogg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Drawing Template -->
- <extension>otg </extension>
- <mime-type>application/vnd.oasis.opendocument.graphics-template</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- HTML Document Template -->
- <extension>oth</extension>
- <mime-type>application/vnd.oasis.opendocument.text-web</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Presentation Template -->
- <extension>otp</extension>
- <mime-type>application/vnd.oasis.opendocument.presentation-template</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Spreadsheet Template -->
- <extension>ots</extension>
- <mime-type>application/vnd.oasis.opendocument.spreadsheet-template </mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Text Template -->
- <extension>ott</extension>
- <mime-type>application/vnd.oasis.opendocument.text-template</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pbm</extension>
- <mime-type>image/x-portable-bitmap</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pct</extension>
- <mime-type>image/pict</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pdf</extension>
- <mime-type>application/pdf</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pgm</extension>
- <mime-type>image/x-portable-graymap</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pic</extension>
- <mime-type>image/pict</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pict</extension>
- <mime-type>image/pict</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pls</extension>
- <mime-type>audio/x-scpls</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>png</extension>
- <mime-type>image/png</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pnm</extension>
- <mime-type>image/x-portable-anymap</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pnt</extension>
- <mime-type>image/x-macpaint</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ppm</extension>
- <mime-type>image/x-portable-pixmap</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ppt</extension>
- <mime-type>application/vnd.ms-powerpoint</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pps</extension>
- <mime-type>application/vnd.ms-powerpoint</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ps</extension>
- <mime-type>application/postscript</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>psd</extension>
- <mime-type>image/x-photoshop</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>qt</extension>
- <mime-type>video/quicktime</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>qti</extension>
- <mime-type>image/x-quicktime</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>qtif</extension>
- <mime-type>image/x-quicktime</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ras</extension>
- <mime-type>image/x-cmu-raster</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>rdf</extension>
- <mime-type>application/rdf+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>rgb</extension>
- <mime-type>image/x-rgb</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>rm</extension>
- <mime-type>application/vnd.rn-realmedia</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>roff</extension>
- <mime-type>application/x-troff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>rtf</extension>
- <mime-type>application/rtf</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>rtx</extension>
- <mime-type>text/richtext</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>sh</extension>
- <mime-type>application/x-sh</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>shar</extension>
- <mime-type>application/x-shar</mime-type>
- </mime-mapping>
-<!--
- <mime-mapping>
- <extension>shtml</extension>
- <mime-type>text/x-server-parsed-html</mime-type>
- </mime-mapping>
--->
- <mime-mapping>
- <extension>smf</extension>
- <mime-type>audio/x-midi</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>sit</extension>
- <mime-type>application/x-stuffit</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>snd</extension>
- <mime-type>audio/basic</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>src</extension>
- <mime-type>application/x-wais-source</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>sv4cpio</extension>
- <mime-type>application/x-sv4cpio</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>sv4crc</extension>
- <mime-type>application/x-sv4crc</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>svg</extension>
- <mime-type>image/svg+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>svgz</extension>
- <mime-type>image/svg+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>swf</extension>
- <mime-type>application/x-shockwave-flash</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>t</extension>
- <mime-type>application/x-troff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>tar</extension>
- <mime-type>application/x-tar</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>tcl</extension>
- <mime-type>application/x-tcl</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>tex</extension>
- <mime-type>application/x-tex</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>texi</extension>
- <mime-type>application/x-texinfo</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>texinfo</extension>
- <mime-type>application/x-texinfo</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>tif</extension>
- <mime-type>image/tiff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>tiff</extension>
- <mime-type>image/tiff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>tr</extension>
- <mime-type>application/x-troff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>tsv</extension>
- <mime-type>text/tab-separated-values</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>txt</extension>
- <mime-type>text/plain</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ulw</extension>
- <mime-type>audio/basic</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ustar</extension>
- <mime-type>application/x-ustar</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>vxml</extension>
- <mime-type>application/voicexml+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xbm</extension>
- <mime-type>image/x-xbitmap</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xht</extension>
- <mime-type>application/xhtml+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xhtml</extension>
- <mime-type>application/xhtml+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xls</extension>
- <mime-type>application/vnd.ms-excel</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xml</extension>
- <mime-type>application/xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xpm</extension>
- <mime-type>image/x-xpixmap</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xsl</extension>
- <mime-type>application/xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xslt</extension>
- <mime-type>application/xslt+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xul</extension>
- <mime-type>application/vnd.mozilla.xul+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xwd</extension>
- <mime-type>image/x-xwindowdump</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>vsd</extension>
- <mime-type>application/x-visio</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>wav</extension>
- <mime-type>audio/x-wav</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- Wireless Bitmap -->
- <extension>wbmp</extension>
- <mime-type>image/vnd.wap.wbmp</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- WML Source -->
- <extension>wml</extension>
- <mime-type>text/vnd.wap.wml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- Compiled WML -->
- <extension>wmlc</extension>
- <mime-type>application/vnd.wap.wmlc</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- WML Script Source -->
- <extension>wmls</extension>
- <mime-type>text/vnd.wap.wmlscript</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- Compiled WML Script -->
- <extension>wmlscriptc</extension>
- <mime-type>application/vnd.wap.wmlscriptc</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>wmv</extension>
- <mime-type>video/x-ms-wmv</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>wrl</extension>
- <mime-type>x-world/x-vrml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>wspolicy</extension>
- <mime-type>application/wspolicy+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>Z</extension>
- <mime-type>application/x-compress</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>z</extension>
- <mime-type>application/x-compress</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>zip</extension>
- <mime-type>application/zip</mime-type>
- </mime-mapping>
-
- <!-- ==================== Default Welcome File List ===================== -->
- <!-- When a request URI refers to a directory, the default servlet looks -->
- <!-- for a "welcome file" within that directory and, if present, -->
- <!-- to the corresponding resource URI for display. If no welcome file -->
- <!-- is present, the default servlet either serves a directory listing, -->
- <!-- or returns a 404 status, depending on how it is configured. -->
- <!-- -->
- <!-- If you define welcome files in your own application's web.xml -->
- <!-- deployment descriptor, that list *replaces* the list configured -->
- <!-- here, so be sure that you include any of the default values that -->
- <!-- you wish to include. -->
-
- <welcome-file-list>
- <welcome-file>index.html</welcome-file>
- <welcome-file>index.htm</welcome-file>
- </welcome-file-list>
-
-</web-app>
diff --git a/core/pom.xml b/core/pom.xml
index 5e6521e8c23..469731177b3 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -25,7 +25,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
@@ -50,7 +50,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
- <version>1.12</version>
+ <version>1.14</version>
</dependency>
</dependencies>
diff --git a/packaging/centos63/tomcat.sh b/core/resources/META-INF/cloudstack/ca/module.properties
similarity index 95%
rename from packaging/centos63/tomcat.sh
rename to core/resources/META-INF/cloudstack/ca/module.properties
index 0908da4696e..1a6915aea90 100644
--- a/packaging/centos63/tomcat.sh
+++ b/core/resources/META-INF/cloudstack/ca/module.properties
@@ -1,3 +1,4 @@
+#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
@@ -14,5 +15,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
+#
-. /etc/rc.d/init.d/tomcat6 start
+name=ca
+parent=backend
diff --git a/core/resources/META-INF/cloudstack/ca/spring-core-lifecycle-ca-context-inheritable.xml b/core/resources/META-INF/cloudstack/ca/spring-core-lifecycle-ca-context-inheritable.xml
new file mode 100644
index 00000000000..1566a4b076b
--- /dev/null
+++ b/core/resources/META-INF/cloudstack/ca/spring-core-lifecycle-ca-context-inheritable.xml
@@ -0,0 +1,32 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
+>
+
+ <bean class="org.apache.cloudstack.spring.lifecycle.registry.RegistryLifecycle">
+ <property name="registry" ref="caProvidersRegistry" />
+ <property name="typeClass" value="org.apache.cloudstack.framework.ca.CAProvider" />
+ </bean>
+
+</beans>
diff --git a/core/resources/META-INF/cloudstack/compute/spring-core-lifecycle-compute-context-inheritable.xml b/core/resources/META-INF/cloudstack/compute/spring-core-lifecycle-compute-context-inheritable.xml
index 293834eda8a..fb0e8780ecc 100644
--- a/core/resources/META-INF/cloudstack/compute/spring-core-lifecycle-compute-context-inheritable.xml
+++ b/core/resources/META-INF/cloudstack/compute/spring-core-lifecycle-compute-context-inheritable.xml
@@ -44,4 +44,9 @@
<property name="typeClass" value="com.cloud.hypervisor.HypervisorGuru" />
</bean>
+ <bean class="org.apache.cloudstack.spring.lifecycle.registry.RegistryLifecycle">
+ <property name="registry" ref="haProvidersRegistry" />
+ <property name="typeClass" value="org.apache.cloudstack.ha.provider.HAProvider" />
+ </bean>
+
</beans>
diff --git a/core/resources/META-INF/cloudstack/core/spring-core-registry-core-context.xml b/core/resources/META-INF/cloudstack/core/spring-core-registry-core-context.xml
index a9124d37ac1..feca134a197 100644
--- a/core/resources/META-INF/cloudstack/core/spring-core-registry-core-context.xml
+++ b/core/resources/META-INF/cloudstack/core/spring-core-registry-core-context.xml
@@ -134,7 +134,6 @@
<bean id="ipDeployersRegistry"
class="org.apache.cloudstack.spring.lifecycle.registry.ExtensionRegistry">
<property name="excludeKey" value="ip.deployers.exclude" />
- <property name="excludeDefault" value="MidoNetElement" />
<property name="preRegistered">
<list>
<ref bean="VpcVirtualRouter" />
@@ -145,7 +144,6 @@
<bean id="dhcpProvidersRegistry"
class="org.apache.cloudstack.spring.lifecycle.registry.ExtensionRegistry">
<property name="excludeKey" value="dhcp.providers.exclude" />
- <property name="excludeDefault" value="MidoNetElement" />
<property name="preRegistered">
<list>
<ref bean="VpcVirtualRouter" />
@@ -307,9 +305,18 @@
<property name="excludeKey" value="data.motion.strategies.exclude" />
</bean>
+ <bean id="haProvidersRegistry"
+ class="org.apache.cloudstack.spring.lifecycle.registry.ExtensionRegistry">
+ <property name="orderConfigDefault" value="KVMHAProvider" />
+ </bean>
+
<bean id="outOfBandManagementDriversRegistry"
class="org.apache.cloudstack.spring.lifecycle.registry.ExtensionRegistry">
<property name="orderConfigDefault" value="IPMITOOL" />
</bean>
+ <bean id="caProvidersRegistry"
+ class="org.apache.cloudstack.spring.lifecycle.registry.ExtensionRegistry">
+ </bean>
+
</beans>
diff --git a/core/src/com/cloud/agent/api/CheckVMActivityOnStoragePoolCommand.java b/core/src/com/cloud/agent/api/CheckVMActivityOnStoragePoolCommand.java
new file mode 100644
index 00000000000..b053f2895d2
--- /dev/null
+++ b/core/src/com/cloud/agent/api/CheckVMActivityOnStoragePoolCommand.java
@@ -0,0 +1,70 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package com.cloud.agent.api;
+
+import com.cloud.agent.api.to.HostTO;
+import com.cloud.agent.api.to.StorageFilerTO;
+import com.cloud.host.Host;
+import com.cloud.storage.StoragePool;
+import com.cloud.storage.Volume;
+
+import org.joda.time.DateTime;
+import java.util.List;
+
+public final class CheckVMActivityOnStoragePoolCommand extends Command {
+
+ private HostTO host;
+ private StorageFilerTO pool;
+ private String volumeList;
+ private long suspectTimeSeconds;
+
+ public CheckVMActivityOnStoragePoolCommand(final Host host, final StoragePool pool, final List<Volume> volumeList, final DateTime suspectTime) {
+ this.host = new HostTO(host);
+ this.pool = new StorageFilerTO(pool);
+ this.suspectTimeSeconds = suspectTime.getMillis()/1000L;
+ final StringBuilder stringBuilder = new StringBuilder();
+ for (final Volume v : volumeList) {
+ stringBuilder.append(v.getUuid()).append(",");
+ }
+
+ this.volumeList = stringBuilder.deleteCharAt(stringBuilder.length() - 1).toString();
+ }
+
+ public String getVolumeList() {
+ return volumeList;
+ }
+
+ public StorageFilerTO getPool() {
+ return pool;
+ }
+
+ public HostTO getHost() {
+ return host;
+ }
+
+ public long getSuspectTimeInSeconds() {
+ return suspectTimeSeconds;
+ }
+
+ @Override
+ public boolean executeInSequence() {
+ return false;
+ }
+}
diff --git a/core/src/com/cloud/agent/api/ComputeChecksumCommand.java b/core/src/com/cloud/agent/api/ComputeChecksumCommand.java
index 5c8c929ce6f..fc7c55d6f52 100644
--- a/core/src/com/cloud/agent/api/ComputeChecksumCommand.java
+++ b/core/src/com/cloud/agent/api/ComputeChecksumCommand.java
@@ -25,6 +25,7 @@
public class ComputeChecksumCommand extends SsCommand {
private DataStoreTO store;
private String templatePath;
+ private String algorithm = "MD5";
public ComputeChecksumCommand() {
super();
@@ -35,6 +36,11 @@ public ComputeChecksumCommand(DataStoreTO store, String templatePath) {
this.setStore(store);
}
+ public ComputeChecksumCommand(DataStoreTO store, String templatePath, String algorithm) {
+ this(store,templatePath);
+ this.algorithm = algorithm;
+ }
+
public String getTemplatePath() {
return templatePath;
}
@@ -43,8 +49,12 @@ public DataStoreTO getStore() {
return store;
}
- public void setStore(DataStoreTO store) {
- this.store = store;
+
+ public String getAlgorithm() {
+ return algorithm;
}
+ void setStore(DataStoreTO store) {
+ this.store = store;
+ }
}
diff --git a/core/src/com/cloud/agent/api/ExternalNetworkResourceUsageCommand.java b/core/src/com/cloud/agent/api/ExternalNetworkResourceUsageCommand.java
index 09dc80b7bb0..6986c406c93 100644
--- a/core/src/com/cloud/agent/api/ExternalNetworkResourceUsageCommand.java
+++ b/core/src/com/cloud/agent/api/ExternalNetworkResourceUsageCommand.java
@@ -20,12 +20,21 @@
package com.cloud.agent.api;
public class ExternalNetworkResourceUsageCommand extends Command {
+ Long networkid;
public ExternalNetworkResourceUsageCommand() {
}
+ public ExternalNetworkResourceUsageCommand(Long networkid) {
+ this.networkid = networkid;
+ }
+
@Override
public boolean executeInSequence() {
return false;
}
+
+ public Long getNetworkid() {
+ return networkid;
+ }
}
diff --git a/core/src/com/cloud/agent/api/GetVmDiskStatsAnswer.java b/core/src/com/cloud/agent/api/GetVmDiskStatsAnswer.java
index 77fe8ae62d2..cb52c462d65 100644
--- a/core/src/com/cloud/agent/api/GetVmDiskStatsAnswer.java
+++ b/core/src/com/cloud/agent/api/GetVmDiskStatsAnswer.java
@@ -24,7 +24,7 @@
import com.cloud.agent.api.LogLevel.Log4jLevel;
-@LogLevel(Log4jLevel.Trace)
+@LogLevel(Log4jLevel.Debug)
public class GetVmDiskStatsAnswer extends Answer {
String hostName;
diff --git a/core/src/com/cloud/agent/api/GetVmNetworkStatsAnswer.java b/core/src/com/cloud/agent/api/GetVmNetworkStatsAnswer.java
new file mode 100644
index 00000000000..85a99cb1f41
--- /dev/null
+++ b/core/src/com/cloud/agent/api/GetVmNetworkStatsAnswer.java
@@ -0,0 +1,50 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package com.cloud.agent.api;
+
+import java.util.HashMap;
+import java.util.List;
+
+import com.cloud.agent.api.LogLevel.Log4jLevel;
+
+@LogLevel(Log4jLevel.Debug)
+public class GetVmNetworkStatsAnswer extends Answer {
+
+ String hostName;
+ HashMap<String, List<VmNetworkStatsEntry>> vmNetworkStatsMap;
+
+ public GetVmNetworkStatsAnswer(GetVmNetworkStatsCommand cmd, String details, String hostName, HashMap<String, List<VmNetworkStatsEntry>> vmNetworkStatsMap) {
+ super(cmd, true, details);
+ this.hostName = hostName;
+ this.vmNetworkStatsMap = vmNetworkStatsMap;
+ }
+
+ public String getHostName() {
+ return hostName;
+ }
+
+ public HashMap<String, List<VmNetworkStatsEntry>> getVmNetworkStatsMap() {
+ return vmNetworkStatsMap;
+ }
+
+ protected GetVmNetworkStatsAnswer() {
+ //no-args constructor for json serialization-deserialization
+ }
+}
diff --git a/core/src/com/cloud/agent/api/GetVmNetworkStatsCommand.java b/core/src/com/cloud/agent/api/GetVmNetworkStatsCommand.java
new file mode 100644
index 00000000000..266045e8115
--- /dev/null
+++ b/core/src/com/cloud/agent/api/GetVmNetworkStatsCommand.java
@@ -0,0 +1,57 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package com.cloud.agent.api;
+
+import java.util.List;
+
+import com.cloud.agent.api.LogLevel.Log4jLevel;
+
+@LogLevel(Log4jLevel.Trace)
+public class GetVmNetworkStatsCommand extends Command {
+ List<String> vmNames;
+ String hostGuid;
+ String hostName;
+
+ protected GetVmNetworkStatsCommand() {
+ }
+
+ public GetVmNetworkStatsCommand(List<String> vmNames, String hostGuid, String hostName) {
+ this.vmNames = vmNames;
+ this.hostGuid = hostGuid;
+ this.hostName = hostName;
+ }
+
+ public List<String> getVmNames() {
+ return vmNames;
+ }
+
+ public String getHostGuid() {
+ return this.hostGuid;
+ }
+
+ public String getHostName() {
+ return this.hostName;
+ }
+
+ @Override
+ public boolean executeInSequence() {
+ return false;
+ }
+}
diff --git a/core/src/com/cloud/agent/api/NetScalerImplementNetworkCommand.java b/core/src/com/cloud/agent/api/NetScalerImplementNetworkCommand.java
new file mode 100644
index 00000000000..06e4eb84f1b
--- /dev/null
+++ b/core/src/com/cloud/agent/api/NetScalerImplementNetworkCommand.java
@@ -0,0 +1,65 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package com.cloud.agent.api;
+
+public class NetScalerImplementNetworkCommand extends Command {
+ private String _networkDetails;
+
+ public NetScalerImplementNetworkCommand() {
+ super();
+ }
+
+ private String dcId;
+ private Long hostId;
+
+ public NetScalerImplementNetworkCommand(String dcId) {
+ super();
+ this.dcId = dcId;
+ }
+
+ public NetScalerImplementNetworkCommand(String dcId, Long hostId, String networkDetails) {
+ this(dcId);
+ this.hostId = hostId;
+ this._networkDetails = networkDetails;
+ }
+
+ public void setDetails(String details) {
+ _networkDetails = details;
+ }
+
+ public String getDetails() {
+ return _networkDetails;
+ }
+
+ public String getDataCenterId() {
+ return dcId;
+ }
+
+ @Override
+ public boolean executeInSequence() {
+ //TODO checkout whether we need to mark it true ??
+ //Marking it true is causing another guest network execution in queue
+ return false;
+ }
+
+ public Long getHostId() {
+ return hostId;
+ }
+}
diff --git a/core/src/com/cloud/agent/api/SecStorageVMSetupCommand.java b/core/src/com/cloud/agent/api/SecStorageVMSetupCommand.java
index 7753f708b0a..400fc5aacdd 100644
--- a/core/src/com/cloud/agent/api/SecStorageVMSetupCommand.java
+++ b/core/src/com/cloud/agent/api/SecStorageVMSetupCommand.java
@@ -19,9 +19,12 @@
package com.cloud.agent.api;
+import com.cloud.agent.api.LogLevel.Log4jLevel;
+
public class SecStorageVMSetupCommand extends Command {
String[] allowedInternalSites = new String[0];
String copyUserName;
+ @LogLevel(Log4jLevel.Off)
String copyPassword;
public SecStorageVMSetupCommand() {
diff --git a/core/src/com/cloud/agent/api/StartupExternalLoadBalancerCommand.java b/core/src/com/cloud/agent/api/StartupExternalLoadBalancerCommand.java
index 50187b2d043..698988ec5ed 100644
--- a/core/src/com/cloud/agent/api/StartupExternalLoadBalancerCommand.java
+++ b/core/src/com/cloud/agent/api/StartupExternalLoadBalancerCommand.java
@@ -26,4 +26,7 @@ public StartupExternalLoadBalancerCommand() {
super(Host.Type.ExternalLoadBalancer);
}
+ public StartupExternalLoadBalancerCommand(Host.Type type) {
+ super(type);
+ }
}
diff --git a/core/src/com/cloud/agent/api/VmNetworkStatsEntry.java b/core/src/com/cloud/agent/api/VmNetworkStatsEntry.java
new file mode 100644
index 00000000000..41db54a822e
--- /dev/null
+++ b/core/src/com/cloud/agent/api/VmNetworkStatsEntry.java
@@ -0,0 +1,74 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package com.cloud.agent.api;
+
+import com.cloud.vm.VmNetworkStats;
+
+public class VmNetworkStatsEntry implements VmNetworkStats {
+ String vmName;
+ String macAddress;
+ long bytesSent;
+ long bytesReceived;
+
+ public VmNetworkStatsEntry() {
+ }
+
+ public VmNetworkStatsEntry(String vmName, String macAddress, long bytesSent, long bytesReceived) {
+ this.bytesSent = bytesSent;
+ this.bytesReceived = bytesReceived;
+ this.vmName = vmName;
+ this.macAddress = macAddress;
+ }
+
+ public void setVmName(String vmName) {
+ this.vmName = vmName;
+ }
+
+ public String getVmName() {
+ return vmName;
+ }
+
+ public void setMacAddress(String macAddress) {
+ this.macAddress = macAddress;
+ }
+
+ public String getMacAddress() {
+ return macAddress;
+ }
+
+ public void setBytesSent(long bytesSent) {
+ this.bytesSent = bytesSent;
+ }
+
+ @Override
+ public long getBytesSent() {
+ return bytesSent;
+ }
+
+ public void setBytesReceived(long bytesReceived) {
+ this.bytesReceived = bytesReceived;
+ }
+
+ @Override
+ public long getBytesReceived() {
+ return bytesReceived;
+ }
+
+}
diff --git a/core/src/com/cloud/agent/api/routing/HealthCheckLBConfigCommand.java b/core/src/com/cloud/agent/api/routing/HealthCheckLBConfigCommand.java
index d30fed4bdfb..ee401f64da0 100644
--- a/core/src/com/cloud/agent/api/routing/HealthCheckLBConfigCommand.java
+++ b/core/src/com/cloud/agent/api/routing/HealthCheckLBConfigCommand.java
@@ -26,16 +26,20 @@
*/
public class HealthCheckLBConfigCommand extends NetworkElementCommand {
LoadBalancerTO[] loadBalancers;
-
+ long networkId;
protected HealthCheckLBConfigCommand() {
}
- public HealthCheckLBConfigCommand(LoadBalancerTO[] loadBalancers) {
+ public HealthCheckLBConfigCommand(LoadBalancerTO[] loadBalancers, long networkid) {
this.loadBalancers = loadBalancers;
+ this.networkId = networkid;
}
public LoadBalancerTO[] getLoadBalancers() {
return loadBalancers;
}
+ public long getNetworkId() {
+ return networkId;
+ }
}
diff --git a/core/src/com/cloud/agent/api/routing/NetworkElementCommand.java b/core/src/com/cloud/agent/api/routing/NetworkElementCommand.java
index a7b5b5e6d17..ae482ac71ec 100644
--- a/core/src/com/cloud/agent/api/routing/NetworkElementCommand.java
+++ b/core/src/com/cloud/agent/api/routing/NetworkElementCommand.java
@@ -20,6 +20,7 @@
package com.cloud.agent.api.routing;
import java.util.HashMap;
+import java.util.Map;
import com.cloud.agent.api.Command;
@@ -46,6 +47,18 @@ protected NetworkElementCommand() {
super();
}
+ public void setAccessDetail(final Map<String, String> details) {
+ if (details == null) {
+ return;
+ }
+ for (final Map.Entry<String, String> detail : details.entrySet()) {
+ if (detail == null) {
+ continue;
+ }
+ setAccessDetail(detail.getKey(), detail.getValue());
+ }
+ }
+
public void setAccessDetail(final String name, final String value) {
accessDetails.put(name, value);
}
diff --git a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java
index 75f55f949a2..d7c3d56f9b9 100644
--- a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java
+++ b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java
@@ -35,6 +35,11 @@
import javax.naming.ConfigurationException;
+import org.apache.cloudstack.ca.SetupCertificateAnswer;
+import org.apache.cloudstack.ca.SetupCertificateCommand;
+import org.apache.cloudstack.ca.SetupKeyStoreCommand;
+import org.apache.cloudstack.ca.SetupKeystoreAnswer;
+import org.apache.cloudstack.utils.security.KeyStoreUtils;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
@@ -108,6 +113,14 @@ public Answer executeRequest(final NetworkElementCommand cmd) {
return executeQueryCommand(cmd);
}
+ if (cmd instanceof SetupKeyStoreCommand) {
+ return execute((SetupKeyStoreCommand) cmd);
+ }
+
+ if (cmd instanceof SetupCertificateCommand) {
+ return execute((SetupCertificateCommand) cmd);
+ }
+
if (cmd instanceof AggregationControlCommand) {
return execute((AggregationControlCommand)cmd);
}
@@ -139,6 +152,37 @@ public Answer executeRequest(final NetworkElementCommand cmd) {
}
}
+ private Answer execute(final SetupKeyStoreCommand cmd) {
+ final String args = String.format("/usr/local/cloud/systemvm/conf/agent.properties " +
+ "/usr/local/cloud/systemvm/conf/%s " +
+ "%s %d " +
+ "/usr/local/cloud/systemvm/conf/%s",
+ KeyStoreUtils.defaultKeystoreFile,
+ cmd.getKeystorePassword(),
+ cmd.getValidityDays(),
+ KeyStoreUtils.defaultCsrFile);
+ ExecutionResult result = _vrDeployer.executeInVR(cmd.getRouterAccessIp(), KeyStoreUtils.keyStoreSetupScript, args);
+ return new SetupKeystoreAnswer(result.getDetails());
+ }
+
+ private Answer execute(final SetupCertificateCommand cmd) {
+ final String args = String.format("/usr/local/cloud/systemvm/conf/agent.properties " +
+ "/usr/local/cloud/systemvm/conf/%s %s " +
+ "/usr/local/cloud/systemvm/conf/%s \"%s\" " +
+ "/usr/local/cloud/systemvm/conf/%s \"%s\" " +
+ "/usr/local/cloud/systemvm/conf/%s \"%s\"",
+ KeyStoreUtils.defaultKeystoreFile,
+ KeyStoreUtils.sshMode,
+ KeyStoreUtils.defaultCertFile,
+ cmd.getEncodedCertificate(),
+ KeyStoreUtils.defaultCaCertFile,
+ cmd.getEncodedCaCertificates(),
+ KeyStoreUtils.defaultPrivateKeyFile,
+ cmd.getEncodedPrivateKey());
+ ExecutionResult result = _vrDeployer.executeInVR(cmd.getRouterAccessIp(), KeyStoreUtils.keyStoreImportScript, args);
+ return new SetupCertificateAnswer(result.isSuccess());
+ }
+
private Answer executeQueryCommand(NetworkElementCommand cmd) {
if (cmd instanceof CheckRouterCommand) {
return execute((CheckRouterCommand)cmd);
diff --git a/core/src/com/cloud/storage/template/HttpTemplateDownloader.java b/core/src/com/cloud/storage/template/HttpTemplateDownloader.java
index bdf49900b1f..d3c23a1fddb 100644
--- a/core/src/com/cloud/storage/template/HttpTemplateDownloader.java
+++ b/core/src/com/cloud/storage/template/HttpTemplateDownloader.java
@@ -62,7 +62,7 @@
private static final int CHUNK_SIZE = 1024 * 1024; //1M
private String downloadUrl;
private String toFile;
- public TemplateDownloader.Status status = TemplateDownloader.Status.NOT_STARTED;
+ public TemplateDownloader.Status status;
public String errorString = " ";
private long remoteSize = 0;
public long downloadTime = 0;
@@ -83,41 +83,38 @@ public HttpTemplateDownloader(StorageLayer storageLayer, String downloadUrl, Str
String user, String password, Proxy proxy, ResourceType resourceType) {
_storage = storageLayer;
this.downloadUrl = downloadUrl;
- setToDir(toDir);
- status = TemplateDownloader.Status.NOT_STARTED;
+ this.toDir = toDir;
this.resourceType = resourceType;
this.maxTemplateSizeInBytes = maxTemplateSizeInBytes;
+ completionCallback = callback;
+ status = TemplateDownloader.Status.NOT_STARTED;
totalBytes = 0;
client = new HttpClient(s_httpClientManager);
+ myretryhandler = createRetryTwiceHandler();
+ try {
+ request = createRequest(downloadUrl);
+ checkTemporaryDestination(toDir);
+ checkProxy(proxy);
+ checkCredentials(user, password);
+ } catch (Exception ex) {
+ errorString = "Unable to start download -- check url? ";
+ status = TemplateDownloader.Status.UNRECOVERABLE_ERROR;
+ s_logger.warn("Exception in constructor -- " + ex.toString());
+ } catch (Throwable th) {
+ s_logger.warn("throwable caught ", th);
+ }
+ }
- myretryhandler = new HttpMethodRetryHandler() {
- @Override
- public boolean retryMethod(final HttpMethod method, final IOException exception, int executionCount) {
- if (executionCount >= 2) {
- // Do not retry if over max retry count
- return false;
- }
- if (exception instanceof NoHttpResponseException) {
- // Retry if the server dropped connection on us
- return true;
- }
- if (!method.isRequestSent()) {
- // Retry if the request has not been sent fully or
- // if it's OK to retry methods that have been sent
- return true;
- }
- // otherwise do not retry
- return false;
- }
- };
+ private GetMethod createRequest(String downloadUrl) {
+ GetMethod request = new GetMethod(downloadUrl);
+ request.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, myretryhandler);
+ request.setFollowRedirects(true);
+ return request;
+ }
+ private void checkTemporaryDestination(String toDir) {
try {
- request = new GetMethod(downloadUrl);
- request.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, myretryhandler);
- completionCallback = callback;
- this.request.setFollowRedirects(true);
-
File f = File.createTempFile("dnld", "tmp_", new File(toDir));
if (_storage != null) {
@@ -125,15 +122,16 @@ public boolean retryMethod(final HttpMethod method, final IOException exception,
}
toFile = f.getAbsolutePath();
- Pair<String, Integer> hostAndPort = UriUtils.validateUrl(downloadUrl);
+ } catch (IOException ex) {
+ errorString = "Unable to start download -- check url? ";
+ status = TemplateDownloader.Status.UNRECOVERABLE_ERROR;
+ s_logger.warn("Exception in constructor -- " + ex.toString());
+ }
+ }
- if (proxy != null) {
- client.getHostConfiguration().setProxy(proxy.getHost(), proxy.getPort());
- if (proxy.getUserName() != null) {
- Credentials proxyCreds = new UsernamePasswordCredentials(proxy.getUserName(), proxy.getPassword());
- client.getState().setProxyCredentials(AuthScope.ANY, proxyCreds);
- }
- }
+ private void checkCredentials(String user, String password) {
+ try {
+ Pair<String, Integer> hostAndPort = UriUtils.validateUrl(downloadUrl);
if ((user != null) && (password != null)) {
client.getParams().setAuthenticationPreemptive(true);
Credentials defaultcreds = new UsernamePasswordCredentials(user, password);
@@ -146,150 +144,74 @@ public boolean retryMethod(final HttpMethod method, final IOException exception,
errorString = iae.getMessage();
status = TemplateDownloader.Status.UNRECOVERABLE_ERROR;
inited = false;
- } catch (Exception ex) {
- errorString = "Unable to start download -- check url? ";
- status = TemplateDownloader.Status.UNRECOVERABLE_ERROR;
- s_logger.warn("Exception in constructor -- " + ex.toString());
- } catch (Throwable th) {
- s_logger.warn("throwable caught ", th);
}
}
+ private void checkProxy(Proxy proxy) {
+ if (proxy != null) {
+ client.getHostConfiguration().setProxy(proxy.getHost(), proxy.getPort());
+ if (proxy.getUserName() != null) {
+ Credentials proxyCreds = new UsernamePasswordCredentials(proxy.getUserName(), proxy.getPassword());
+ client.getState().setProxyCredentials(AuthScope.ANY, proxyCreds);
+ }
+ }
+ }
+
+ private HttpMethodRetryHandler createRetryTwiceHandler() {
+ return new HttpMethodRetryHandler() {
+ @Override
+ public boolean retryMethod(final HttpMethod method, final IOException exception, int executionCount) {
+ if (executionCount >= 2) {
+ // Do not retry if over max retry count
+ return false;
+ }
+ if (exception instanceof NoHttpResponseException) {
+ // Retry if the server dropped connection on us
+ return true;
+ }
+ if (!method.isRequestSent()) {
+ // Retry if the request has not been sent fully or
+ // if it's OK to retry methods that have been sent
+ return true;
+ }
+ // otherwise do not retry
+ return false;
+ }
+ };
+ }
+
@Override
public long download(boolean resume, DownloadCompleteCallback callback) {
- switch (status) {
- case ABORTED:
- case UNRECOVERABLE_ERROR:
- case DOWNLOAD_FINISHED:
- return 0;
- default:
-
- }
+ if (skipDownloadOnStatus()) return 0;
int bytes = 0;
File file = new File(toFile);
try {
- long localFileSize = 0;
- if (file.exists() && resume) {
- localFileSize = file.length();
- s_logger.info("Resuming download to file (current size)=" + localFileSize);
- }
+ long localFileSize = checkLocalFileSizeForResume(resume, file);
Date start = new Date();
- int responseCode = 0;
+ if (checkServerResponse(localFileSize)) return 0;
- if (localFileSize > 0) {
- // require partial content support for resume
- request.addRequestHeader("Range", "bytes=" + localFileSize + "-");
- if (client.executeMethod(request) != HttpStatus.SC_PARTIAL_CONTENT) {
- errorString = "HTTP Server does not support partial get";
- status = TemplateDownloader.Status.UNRECOVERABLE_ERROR;
- return 0;
- }
- } else if ((responseCode = client.executeMethod(request)) != HttpStatus.SC_OK) {
- status = TemplateDownloader.Status.UNRECOVERABLE_ERROR;
- errorString = " HTTP Server returned " + responseCode + " (expected 200 OK) ";
- return 0; //FIXME: retry?
- }
+ if (!tryAndGetRemoteSize()) return 0;
- Header contentLengthHeader = request.getResponseHeader("Content-Length");
- boolean chunked = false;
- long remoteSize2 = 0;
- if (contentLengthHeader == null) {
- Header chunkedHeader = request.getResponseHeader("Transfer-Encoding");
- if (chunkedHeader == null || !"chunked".equalsIgnoreCase(chunkedHeader.getValue())) {
- status = TemplateDownloader.Status.UNRECOVERABLE_ERROR;
- errorString = " Failed to receive length of download ";
- return 0; //FIXME: what status do we put here? Do we retry?
- } else if ("chunked".equalsIgnoreCase(chunkedHeader.getValue())) {
- chunked = true;
- }
- } else {
- remoteSize2 = Long.parseLong(contentLengthHeader.getValue());
- if (remoteSize2 == 0) {
- status = TemplateDownloader.Status.DOWNLOAD_FINISHED;
- String downloaded = "(download complete remote=" + remoteSize + "bytes)";
- errorString = "Downloaded " + totalBytes + " bytes " + downloaded;
- downloadTime = 0;
- return 0;
- }
- }
+ if (!canHandleDownloadSize()) return 0;
- if (remoteSize == 0) {
- remoteSize = remoteSize2;
- }
+ checkAndSetDownloadSize();
- if (remoteSize > maxTemplateSizeInBytes) {
- s_logger.info("Remote size is too large: " + remoteSize + " , max=" + maxTemplateSizeInBytes);
- status = Status.UNRECOVERABLE_ERROR;
- errorString = "Download file size is too large";
- return 0;
- }
+ try (InputStream in = request.getResponseBodyAsStream();
+ RandomAccessFile out = new RandomAccessFile(file, "rw");
+ ) {
+ out.seek(localFileSize);
- if (remoteSize == 0) {
- remoteSize = maxTemplateSizeInBytes;
- }
+ s_logger.info("Starting download from " + downloadUrl + " to " + toFile + " remoteSize=" + remoteSize + " , max size=" + maxTemplateSizeInBytes);
- InputStream in = request.getResponseBodyAsStream();
-
- RandomAccessFile out = new RandomAccessFile(file, "rw");
- out.seek(localFileSize);
-
- s_logger.info("Starting download from " + getDownloadUrl() + " to " + toFile + " remoteSize=" + remoteSize + " , max size=" + maxTemplateSizeInBytes);
-
- byte[] block = new byte[CHUNK_SIZE];
- long offset = 0;
- boolean done = false;
- boolean verifiedFormat=false;
- status = TemplateDownloader.Status.IN_PROGRESS;
- while (!done && status != Status.ABORTED && offset <= remoteSize) {
- if ((bytes = in.read(block, 0, CHUNK_SIZE)) > -1) {
- out.write(block, 0, bytes);
- offset += bytes;
- out.seek(offset);
- totalBytes += bytes;
- if (!verifiedFormat && (offset >= 1048576 || offset >= remoteSize)) { //let's check format after we get 1MB or full file
- String uripath = null;
- try {
- URI str = new URI(getDownloadUrl());
- uripath = str.getPath();
- } catch (URISyntaxException e) {
- s_logger.warn("Invalid download url: " + getDownloadUrl() + ", This should not happen since we have validated the url before!!");
- }
- String unsupportedFormat = ImageStoreUtil.checkTemplateFormat(file.getAbsolutePath(), uripath);
- if (unsupportedFormat == null || !unsupportedFormat.isEmpty()) {
- try {
- request.abort();
- out.close();
- in.close();
- } catch (Exception ex) {
- s_logger.debug("Error on http connection : " + ex.getMessage());
- }
- status = Status.UNRECOVERABLE_ERROR;
- errorString = "Template content is unsupported, or mismatch between selected format and template content. Found : " + unsupportedFormat;
- return 0;
- }
- s_logger.debug("Verified format of downloading file " + file.getAbsolutePath() + " is supported");
- verifiedFormat = true;
- }
- } else {
- done = true;
- }
- }
- out.getFD().sync();
-
- Date finish = new Date();
- String downloaded = "(incomplete download)";
- if (totalBytes >= remoteSize) {
- status = TemplateDownloader.Status.DOWNLOAD_FINISHED;
- downloaded = "(download complete remote=" + remoteSize + "bytes)";
- }
- errorString = "Downloaded " + totalBytes + " bytes " + downloaded;
- downloadTime += finish.getTime() - start.getTime();
- in.close();
- out.close();
+ if (copyBytes(file, in, out)) return 0;
+ Date finish = new Date();
+ checkDowloadCompletion();
+ downloadTime += finish.getTime() - start.getTime();
+ } finally { /* in.close() and out.close() */ }
return totalBytes;
} catch (HttpException hte) {
status = TemplateDownloader.Status.UNRECOVERABLE_ERROR;
@@ -309,6 +231,133 @@ public long download(boolean resume, DownloadCompleteCallback callback) {
return 0;
}
+ private boolean copyBytes(File file, InputStream in, RandomAccessFile out) throws IOException {
+ int bytes;
+ byte[] block = new byte[CHUNK_SIZE];
+ long offset = 0;
+ boolean done = false;
+ VerifyFormat verifyFormat = new VerifyFormat(file);
+ status = Status.IN_PROGRESS;
+ while (!done && status != Status.ABORTED && offset <= remoteSize) {
+ if ((bytes = in.read(block, 0, CHUNK_SIZE)) > -1) {
+ offset = writeBlock(bytes, out, block, offset);
+ if (!verifyFormat.isVerifiedFormat() && (offset >= 1048576 || offset >= remoteSize)) { //let's check format after we get 1MB or full file
+ verifyFormat.invoke();
+ if (verifyFormat.isInvalid()) return true;
+ }
+ } else {
+ done = true;
+ }
+ }
+ out.getFD().sync();
+ return false;
+ }
+
+ private long writeBlock(int bytes, RandomAccessFile out, byte[] block, long offset) throws IOException {
+ out.write(block, 0, bytes);
+ offset += bytes;
+ out.seek(offset);
+ totalBytes += bytes;
+ return offset;
+ }
+
+ private void checkDowloadCompletion() {
+ String downloaded = "(incomplete download)";
+ if (totalBytes >= remoteSize) {
+ status = Status.DOWNLOAD_FINISHED;
+ downloaded = "(download complete remote=" + remoteSize + "bytes)";
+ }
+ errorString = "Downloaded " + totalBytes + " bytes " + downloaded;
+ }
+
+ private boolean canHandleDownloadSize() {
+ if (remoteSize > maxTemplateSizeInBytes) {
+ s_logger.info("Remote size is too large: " + remoteSize + " , max=" + maxTemplateSizeInBytes);
+ status = Status.UNRECOVERABLE_ERROR;
+ errorString = "Download file size is too large";
+ return false;
+ }
+
+ return true;
+ }
+
+ private void checkAndSetDownloadSize() {
+ if (remoteSize == 0) {
+ remoteSize = maxTemplateSizeInBytes;
+ }
+ }
+
+ private boolean tryAndGetRemoteSize() {
+ Header contentLengthHeader = request.getResponseHeader("Content-Length");
+ boolean chunked = false;
+ long reportedRemoteSize = 0;
+ if (contentLengthHeader == null) {
+ Header chunkedHeader = request.getResponseHeader("Transfer-Encoding");
+ if (chunkedHeader == null || !"chunked".equalsIgnoreCase(chunkedHeader.getValue())) {
+ status = Status.UNRECOVERABLE_ERROR;
+ errorString = " Failed to receive length of download ";
+ return false;
+ } else if ("chunked".equalsIgnoreCase(chunkedHeader.getValue())) {
+ chunked = true;
+ }
+ } else {
+ reportedRemoteSize = Long.parseLong(contentLengthHeader.getValue());
+ if (reportedRemoteSize == 0) {
+ status = Status.DOWNLOAD_FINISHED;
+ String downloaded = "(download complete remote=" + remoteSize + "bytes)";
+ errorString = "Downloaded " + totalBytes + " bytes " + downloaded;
+ downloadTime = 0;
+ return false;
+ }
+ }
+
+ if (remoteSize == 0) {
+ remoteSize = reportedRemoteSize;
+ }
+ return true;
+ }
+
+ private boolean checkServerResponse(long localFileSize) throws IOException {
+ int responseCode = 0;
+
+ if (localFileSize > 0) {
+ // require partial content support for resume
+ request.addRequestHeader("Range", "bytes=" + localFileSize + "-");
+ if (client.executeMethod(request) != HttpStatus.SC_PARTIAL_CONTENT) {
+ errorString = "HTTP Server does not support partial get";
+ status = Status.UNRECOVERABLE_ERROR;
+ return true;
+ }
+ } else if ((responseCode = client.executeMethod(request)) != HttpStatus.SC_OK) {
+ status = Status.UNRECOVERABLE_ERROR;
+ errorString = " HTTP Server returned " + responseCode + " (expected 200 OK) ";
+ return true; //FIXME: retry?
+ }
+ return false;
+ }
+
+ private long checkLocalFileSizeForResume(boolean resume, File file) {
+ // TODO check the status of this downloader as well?
+ long localFileSize = 0;
+ if (file.exists() && resume) {
+ localFileSize = file.length();
+ s_logger.info("Resuming download to file (current size)=" + localFileSize);
+ }
+ return localFileSize;
+ }
+
+ private boolean skipDownloadOnStatus() {
+ switch (status) {
+ case ABORTED:
+ case UNRECOVERABLE_ERROR:
+ case DOWNLOAD_FINISHED:
+ return true;
+ default:
+
+ }
+ return false;
+ }
+
public String getDownloadUrl() {
return downloadUrl;
}
@@ -407,19 +456,12 @@ public void setResume(boolean resume) {
this.resume = resume;
}
- public void setToDir(String toDir) {
- this.toDir = toDir;
- }
-
- public String getToDir() {
- return toDir;
- }
-
@Override
public long getMaxTemplateSizeInBytes() {
return maxTemplateSizeInBytes;
}
+ // TODO move this test code to unit tests or integration tests
public static void main(String[] args) {
String url = "http:// dev.mysql.com/get/Downloads/MySQL-5.0/mysql-noinstall-5.0.77-win32.zip/from/http://mirror.services.wisc.edu/mysql/";
try {
@@ -452,4 +494,48 @@ public ResourceType getResourceType() {
return resourceType;
}
+ private class VerifyFormat {
+ private boolean invalidFormat;
+ private File file;
+ private boolean verifiedFormat;
+
+ public VerifyFormat(File file) {
+ this.file = file;
+ this.verifiedFormat = false;
+ }
+
+ boolean isInvalid() {
+ return invalidFormat;
+ }
+
+ public boolean isVerifiedFormat() {
+ return verifiedFormat;
+ }
+
+ public VerifyFormat invoke() {
+ String uripath = null;
+ try {
+ URI str = new URI(downloadUrl);
+ uripath = str.getPath();
+ } catch (URISyntaxException e) {
+ s_logger.warn("Invalid download url: " + downloadUrl + ", This should not happen since we have validated the url before!!");
+ }
+ String unsupportedFormat = ImageStoreUtil.checkTemplateFormat(file.getAbsolutePath(), uripath);
+ if (unsupportedFormat == null || !unsupportedFormat.isEmpty()) {
+ try {
+ request.abort();
+ } catch (Exception ex) {
+ s_logger.debug("Error on http connection : " + ex.getMessage());
+ }
+ status = Status.UNRECOVERABLE_ERROR;
+ errorString = "Template content is unsupported, or mismatch between selected format and template content. Found : " + unsupportedFormat;
+ invalidFormat = true;
+ } else {
+ s_logger.debug("Verified format of downloading file " + file.getAbsolutePath() + " is supported");
+ verifiedFormat = true;
+ invalidFormat = false;
+ }
+ return this;
+ }
+ }
}
diff --git a/core/src/org/apache/cloudstack/ca/SetupCertificateAnswer.java b/core/src/org/apache/cloudstack/ca/SetupCertificateAnswer.java
new file mode 100644
index 00000000000..4df5d158da9
--- /dev/null
+++ b/core/src/org/apache/cloudstack/ca/SetupCertificateAnswer.java
@@ -0,0 +1,29 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.ca;
+
+import com.cloud.agent.api.Answer;
+
+public class SetupCertificateAnswer extends Answer {
+ public SetupCertificateAnswer(final boolean result) {
+ super(null);
+ this.result = result;
+ }
+}
diff --git a/core/src/org/apache/cloudstack/ca/SetupCertificateCommand.java b/core/src/org/apache/cloudstack/ca/SetupCertificateCommand.java
new file mode 100644
index 00000000000..1cd31509d39
--- /dev/null
+++ b/core/src/org/apache/cloudstack/ca/SetupCertificateCommand.java
@@ -0,0 +1,99 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.ca;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.cloudstack.framework.ca.Certificate;
+import org.apache.cloudstack.utils.security.CertUtils;
+import org.apache.cloudstack.utils.security.KeyStoreUtils;
+
+import com.cloud.agent.api.LogLevel;
+import com.cloud.agent.api.routing.NetworkElementCommand;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+public class SetupCertificateCommand extends NetworkElementCommand {
+ @LogLevel(LogLevel.Log4jLevel.Off)
+ private String certificate;
+ @LogLevel(LogLevel.Log4jLevel.Off)
+ private String privateKey = "";
+ @LogLevel(LogLevel.Log4jLevel.Off)
+ private String caCertificates;
+
+ private boolean handleByAgent = true;
+
+ public SetupCertificateCommand(final Certificate certificate) {
+ super();
+ if (certificate == null) {
+ throw new CloudRuntimeException("A null certificate was provided to setup");
+ }
+ setWait(60);
+ try {
+ this.certificate = CertUtils.x509CertificateToPem(certificate.getClientCertificate());
+ this.caCertificates = CertUtils.x509CertificatesToPem(certificate.getCaCertificates());
+ if (certificate.getPrivateKey() != null) {
+ this.privateKey = CertUtils.privateKeyToPem(certificate.getPrivateKey());
+ }
+ } catch (final IOException e) {
+ throw new CloudRuntimeException("Failed to transform X509 cert to PEM format", e);
+ }
+ }
+
+ @Override
+ public void setAccessDetail(final Map<String, String> accessDetails) {
+ handleByAgent = false;
+ super.setAccessDetail(accessDetails);
+ }
+
+ @Override
+ public void setAccessDetail(String name, String value) {
+ handleByAgent = false;
+ super.setAccessDetail(name, value);
+ }
+
+ public String getPrivateKey() {
+ return privateKey;
+ }
+
+ public String getCertificate() {
+ return certificate;
+ }
+
+ public String getCaCertificates() {
+ return caCertificates;
+ }
+
+ public String getEncodedPrivateKey() {
+ return privateKey.replace("\n", KeyStoreUtils.certNewlineEncoder).replace(" ", KeyStoreUtils.certSpaceEncoder);
+ }
+
+ public String getEncodedCertificate() {
+ return certificate.replace("\n", KeyStoreUtils.certNewlineEncoder).replace(" ", KeyStoreUtils.certSpaceEncoder);
+ }
+
+ public String getEncodedCaCertificates() {
+ return caCertificates.replace("\n", KeyStoreUtils.certNewlineEncoder).replace(" ", KeyStoreUtils.certSpaceEncoder);
+ }
+
+ public boolean isHandleByAgent() {
+ return handleByAgent;
+ }
+}
diff --git a/core/src/org/apache/cloudstack/ca/SetupKeyStoreCommand.java b/core/src/org/apache/cloudstack/ca/SetupKeyStoreCommand.java
new file mode 100644
index 00000000000..7cd5cbee20f
--- /dev/null
+++ b/core/src/org/apache/cloudstack/ca/SetupKeyStoreCommand.java
@@ -0,0 +1,75 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.ca;
+
+import java.util.Map;
+
+import com.cloud.agent.api.LogLevel;
+import com.cloud.agent.api.routing.NetworkElementCommand;
+import com.cloud.utils.PasswordGenerator;
+
+public class SetupKeyStoreCommand extends NetworkElementCommand {
+ @LogLevel(LogLevel.Log4jLevel.Off)
+ private int validityDays;
+ @LogLevel(LogLevel.Log4jLevel.Off)
+ private String keystorePassword;
+
+ private boolean handleByAgent = true;
+
+ public SetupKeyStoreCommand(final int validityDays) {
+ super();
+ setWait(60);
+ this.validityDays = validityDays;
+ if (this.validityDays < 1) {
+ this.validityDays = 1;
+ }
+ this.keystorePassword = PasswordGenerator.generateRandomPassword(16);
+ }
+
+ @Override
+ public void setAccessDetail(final Map<String, String> accessDetails) {
+ handleByAgent = false;
+ super.setAccessDetail(accessDetails);
+ }
+
+
+ @Override
+ public void setAccessDetail(String name, String value) {
+ handleByAgent = false;
+ super.setAccessDetail(name, value);
+ }
+
+ public int getValidityDays() {
+ return validityDays;
+ }
+
+ public String getKeystorePassword() {
+ return keystorePassword;
+ }
+
+ public boolean isHandleByAgent() {
+ return handleByAgent;
+ }
+
+ @Override
+ public boolean executeInSequence() {
+ return false;
+ }
+}
diff --git a/core/src/org/apache/cloudstack/ca/SetupKeystoreAnswer.java b/core/src/org/apache/cloudstack/ca/SetupKeystoreAnswer.java
new file mode 100644
index 00000000000..16ddc96c5ea
--- /dev/null
+++ b/core/src/org/apache/cloudstack/ca/SetupKeystoreAnswer.java
@@ -0,0 +1,37 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.ca;
+
+import com.cloud.agent.api.LogLevel;
+import com.google.common.base.Strings;
+
+public class SetupKeystoreAnswer extends SetupCertificateAnswer {
+ @LogLevel(LogLevel.Log4jLevel.Off)
+ private final String csr;
+
+ public SetupKeystoreAnswer(final String csr) {
+ super(!Strings.isNullOrEmpty(csr));
+ this.csr = csr;
+ }
+
+ public String getCsr() {
+ return csr;
+ }
+}
diff --git a/core/test/org/apache/cloudstack/api/agent/test/CheckOnHostCommandTest.java b/core/test/org/apache/cloudstack/api/agent/test/CheckOnHostCommandTest.java
index 72ec83a41f7..3cba4929a57 100644
--- a/core/test/org/apache/cloudstack/api/agent/test/CheckOnHostCommandTest.java
+++ b/core/test/org/apache/cloudstack/api/agent/test/CheckOnHostCommandTest.java
@@ -27,6 +27,8 @@
import java.text.SimpleDateFormat;
import java.util.Date;
+import org.apache.cloudstack.ha.HAResource;
+import org.apache.cloudstack.kernel.Partition;
import org.junit.Test;
import com.cloud.agent.api.CheckOnHostCommand;
@@ -38,6 +40,11 @@
public class CheckOnHostCommandTest {
public Host host = new Host() {
+ @Override
+ public PartitionType partitionType() {
+ return PartitionType.Host;
+ }
+
@Override
public Status getState() {
return Status.Up;
@@ -197,7 +204,12 @@ public Date getRemoved() {
@Override
public Long getClusterId() {
return 3L;
- };
+ }
+
+ @Override
+ public ResourceType resourceType() {
+ return ResourceType.Host;
+ }
@Override
public String getPublicIpAddress() {
@@ -254,6 +266,11 @@ public boolean isInMaintenanceStates() {
return false;
};
+ @Override
+ public boolean isDisabled() {
+ return false;
+ };
+
@Override
public ResourceState getResourceState() {
return ResourceState.Enabled;
diff --git a/debian/changelog b/debian/changelog
index 27e6dbc9f89..5ee33f2edeb 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,10 +1,10 @@
-cloudstack (4.10.1.0-SNAPSHOT) unstable; urgency=low
+cloudstack (4.11.0.0-SNAPSHOT) unstable; urgency=low
- * Update the version to 4.10.1.0-SNAPSHOT
+ * Update the version to 4.11.0.0-SNAPSHOT
-- the Apache CloudStack project <de...@cloudstack.apache.org> Mon, 03 Jul 2017 10:06:42 +0530
-cloudstack (4.10.1.0-SNAPSHOT-SNAPSHOT) unstable; urgency=low
+cloudstack (4.11.0.0-SNAPSHOT-SNAPSHOT) unstable; urgency=low
* Update the version to 4.10.0.snapshot
diff --git a/debian/cloudstack-agent.postinst b/debian/cloudstack-agent.postinst
old mode 100644
new mode 100755
diff --git a/debian/cloudstack-management.install b/debian/cloudstack-management.install
index 9c3f04e1638..bb241fbec37 100644
--- a/debian/cloudstack-management.install
+++ b/debian/cloudstack-management.install
@@ -15,32 +15,17 @@
# specific language governing permissions and limitations
# under the License.
-/etc/cloudstack/management/catalina.policy
-/etc/cloudstack/management/catalina.properties
-/etc/cloudstack/management/logging.properties
/etc/cloudstack/management/ehcache.xml
-/etc/cloudstack/management/server-ssl.xml
-/etc/cloudstack/management/server-nonssl.xml
-/etc/cloudstack/management/server7-ssl.xml
-/etc/cloudstack/management/server7-nonssl.xml
-/etc/cloudstack/management/classpath.conf
/etc/cloudstack/management/db.properties
-/etc/cloudstack/management/tomcat6-ssl.conf
-/etc/cloudstack/management/tomcat6-nonssl.conf
-/etc/cloudstack/management/tomcat6.conf
-/etc/cloudstack/management/web.xml
/etc/cloudstack/management/environment.properties
+/etc/cloudstack/management/server.properties
/etc/cloudstack/management/java.security.ciphers
/etc/cloudstack/management/log4j-cloud.xml
-/etc/cloudstack/management/tomcat-users.xml
-/etc/cloudstack/management/context.xml
/etc/default/cloudstack-management
/etc/init.d/cloudstack-management
/etc/security/limits.d/cloudstack-limits.conf
/etc/sudoers.d/cloudstack
/var/cache/cloudstack/management
-/var/cache/cloudstack/management/work
-/var/cache/cloudstack/management/temp
/var/log/cloudstack/management
/var/lib/cloudstack/mnt
/var/lib/cloudstack/management
diff --git a/debian/cloudstack-management.postinst b/debian/cloudstack-management.postinst
old mode 100644
new mode 100755
index 240224d9252..b2a1c900a73
--- a/debian/cloudstack-management.postinst
+++ b/debian/cloudstack-management.postinst
@@ -29,8 +29,6 @@ if [ "$1" = configure ]; then
rm -fr /var/cache/cloudstack/management/work/*
for i in /var/cache/cloudstack/management \
- /var/cache/cloudstack/management/work \
- /var/cache/cloudstack/management/temp \
/var/log/cloudstack/management \
/var/lib/cloudstack/management
do
@@ -50,9 +48,6 @@ if [ "$1" = configure ]; then
cp -a $OLDCONFDIR/$FILE $NEWCONFDIR/$FILE
fi
done
- if [ -f "$OLDCONFDIR/cloud.keystore" ]; then
- cp -a $OLDCONFDIR/cloud.keystore $NEWCONFDIR/cloudmanagementserver.keystore
- fi
fi
CONFDIR="/etc/cloudstack/management"
@@ -60,26 +55,9 @@ if [ "$1" = configure ]; then
chmod 0640 ${CONFDIR}/${DBPROPS}
chgrp cloud ${CONFDIR}/${DBPROPS}
+ chown -R cloud:cloud /var/log/cloudstack/management
- if [ -d "/usr/share/tomcat7" ]; then
- rm -f /usr/share/cloudstack-management/bin
- rm -f /usr/share/cloudstack-management/lib
- ln -s /usr/share/tomcat7/bin /usr/share/cloudstack-management/bin
- ln -s /usr/share/tomcat7/lib /usr/share/cloudstack-management/lib
- invoke-rc.d tomcat7 stop || true
- if [ ! -f "/etc/cloudstack/management/server.xml" ]; then
- ln -s /etc/cloudstack/management/server7-nonssl.xml /etc/cloudstack/management/server.xml
- fi
- elif [ -d "/usr/share/tomcat6" ]; then
- rm -f /usr/share/cloudstack-management/bin
- rm -f /usr/share/cloudstack-management/lib
- ln -s /usr/share/tomcat6/bin /usr/share/cloudstack-management/bin
- ln -s /usr/share/tomcat6/lib /usr/share/cloudstack-management/lib
- invoke-rc.d tomcat6 stop || true
- if [ ! -f "/etc/cloudstack/management/server.xml" ]; then
- ln -s /etc/cloudstack/management/server-nonssl.xml /etc/cloudstack/management/server.xml
- fi
- fi
+ ln -s ${CONFDIR}/log4j-cloud.xml ${CONFDIR}/log4j.xml
# Add jdbc MySQL driver settings to db.properties if not present
grep -s -q "db.cloud.driver=jdbc:mysql" ${CONFDIR}/${DBPROPS} || sed -i -e "\$adb.cloud.driver=jdbc:mysql" ${CONFDIR}/${DBPROPS}
diff --git a/packaging/fedora21/cloudstack-sccs b/debian/cloudstack-management.preinst
old mode 100644
new mode 100755
similarity index 65%
rename from packaging/fedora21/cloudstack-sccs
rename to debian/cloudstack-management.preinst
index e05d372c7fe..ebb98522d6f
--- a/packaging/fedora21/cloudstack-sccs
+++ b/debian/cloudstack-management.preinst
@@ -17,4 +17,16 @@
# specific language governing permissions and limitations
# under the License.
-cat /usr/share/cloudstack-common/scripts/gitrev.txt
+set -e
+
+if [ "$1" = upgrade ]; then
+ # Remove old tomcat symlinks and old env file
+ if [ -L "/usr/share/cloudstack-management/lib" ]
+ then
+ rm -f /usr/share/cloudstack-management/bin
+ rm -f /usr/share/cloudstack-management/lib
+ rm -f /usr/share/cloudstack-management/temp
+ rm -f /usr/share/cloudstack-management/work
+ rm -f /etc/default/cloudstack-management
+ fi
+fi
diff --git a/debian/cloudstack-marvin.postinst b/debian/cloudstack-marvin.postinst
old mode 100644
new mode 100755
diff --git a/debian/cloudstack-usage.postinst b/debian/cloudstack-usage.postinst
old mode 100644
new mode 100755
diff --git a/debian/control b/debian/control
index fed6622c95d..009ed20a9bc 100644
--- a/debian/control
+++ b/debian/control
@@ -15,14 +15,15 @@ Description: A common package which contains files which are shared by several C
Package: cloudstack-management
Architecture: all
-Depends: ${python:Depends}, openjdk-8-jre-headless | java8-runtime-headless | java8-runtime | openjdk-7-jre-headless, cloudstack-common (= ${source:Version}), tomcat6 | tomcat7, sudo, jsvc, python-mysql.connector, libmysql-java, augeas-tools, mysql-client, adduser, bzip2, ipmitool, lsb-release, init-system-helpers (>= 1.14~)
+Depends: ${python:Depends}, openjdk-8-jre-headless | java8-runtime-headless | java8-runtime, cloudstack-common (= ${source:Version}), sudo, jsvc, python-mysql.connector, libmysql-java, augeas-tools, mysql-client, adduser, bzip2, ipmitool, lsb-release, init-system-helpers (>= 1.14~)
Conflicts: cloud-server, cloud-client, cloud-client-ui
Description: CloudStack server library
The CloudStack management server
Package: cloudstack-agent
Architecture: all
-Depends: ${python:Depends}, openjdk-8-jre-headless | java8-runtime-headless | java8-runtime, cloudstack-common (= ${source:Version}), lsb-base (>= 4.0), libcommons-daemon-java, openssh-client, qemu-kvm (>= 1.0), libvirt-bin (>= 0.9.8), uuid-runtime, iproute, ebtables, vlan, jsvc, ipset, python-libvirt, ethtool, iptables, lsb-release, init-system-helpers (>= 1.14~)
+Depends: ${python:Depends}, openjdk-8-jre-headless | java8-runtime-headless | java8-runtime, cloudstack-common (= ${source:Version}), lsb-base (>= 4.0), libcommons-daemon-java, openssh-client, qemu-kvm (>= 1.0), libvirt-bin (>= 1.2.2), uuid-runtime, iproute, ebtables, vlan, jsvc, ipset, python-libvirt, ethtool, iptables, lsb-release, init-system-helpers (>= 1.14~)
+Recommends: init-system-helpers
Conflicts: cloud-agent, cloud-agent-libs, cloud-agent-deps, cloud-agent-scripts
Description: CloudStack agent
The CloudStack agent is in charge of managing shared computing resources in
@@ -36,11 +37,6 @@ Description: CloudStack usage monitor
The CloudStack usage monitor provides usage accounting across the entire cloud for
cloud operators to charge based on usage parameters.
-Package: cloudstack-cli
-Architecture: all
-Depends: ${misc:Depends}, cloudstack-common (= ${source:Version})
-Description: The CloudStack CLI called CloudMonkey
-
Package: cloudstack-docs
Architecture: all
Depends: ${misc:Depends}
diff --git a/debian/rules b/debian/rules
index 82a40239cf5..a41b3f9c2b8 100755
--- a/debian/rules
+++ b/debian/rules
@@ -13,7 +13,7 @@ override_dh_auto_configure:
echo VERSION=${VERSION} >> replace.properties.tmp
override_dh_auto_build:
- mvn -T C1.5 clean package -Psystemvm,developer -Dsystemvm \
+ mvn clean package -Psystemvm,developer -Dsystemvm \
-Dcs.replace.properties=replace.properties.tmp \
-Dmaven.repo.local=$(HOME)/.m2/repository \
${ACS_BUILD_OPTS}
@@ -66,39 +66,35 @@ override_dh_auto_install:
mkdir -p $(DESTDIR)/$(SYSCONFDIR)/security/limits.d/
mkdir -p $(DESTDIR)/$(SYSCONFDIR)/sudoers.d/
mkdir -p $(DESTDIR)/usr/share/$(PACKAGE)-management
- mkdir -p $(DESTDIR)/usr/share/$(PACKAGE)-management/webapps/client
- mkdir $(DESTDIR)/usr/share/$(PACKAGE)-management/setup
+ mkdir -p $(DESTDIR)/usr/share/$(PACKAGE)-management/lib
+ mkdir -p $(DESTDIR)/usr/share/$(PACKAGE)-management/setup
mkdir $(DESTDIR)/var/log/$(PACKAGE)/management
mkdir $(DESTDIR)/var/cache/$(PACKAGE)/management
- mkdir $(DESTDIR)/var/cache/$(PACKAGE)/management/work
- mkdir $(DESTDIR)/var/cache/$(PACKAGE)/management/temp
mkdir $(DESTDIR)/var/log/$(PACKAGE)/ipallocator
mkdir $(DESTDIR)/var/lib/$(PACKAGE)/management
mkdir $(DESTDIR)/var/lib/$(PACKAGE)/mnt
cp -r client/target/utilities/scripts/db/* $(DESTDIR)/usr/share/$(PACKAGE)-management/setup/
- cp -r client/target/cloud-client-ui-$(VERSION)/* $(DESTDIR)/usr/share/$(PACKAGE)-management/webapps/client/
+ cp -r client/target/classes/META-INF/webapp $(DESTDIR)/usr/share/$(PACKAGE)-management/webapp
cp server/target/conf/* $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/server/
cp client/target/conf/* $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/management/
+ cp client/target/cloud-client-ui-$(VERSION).jar $(DESTDIR)/usr/share/$(PACKAGE)-management/lib/cloudstack-$(VERSION).jar
+ cp client/target/lib/*jar $(DESTDIR)/usr/share/$(PACKAGE)-management/lib/
# nast hack for a couple of configuration files
mv $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/server/cloudstack-limits.conf $(DESTDIR)/$(SYSCONFDIR)/security/limits.d/
mv $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/server/cloudstack-sudoers $(DESTDIR)/$(SYSCONFDIR)/sudoers.d/$(PACKAGE)
chmod 0440 $(DESTDIR)/$(SYSCONFDIR)/sudoers.d/$(PACKAGE)
- ln -s tomcat6-nonssl.conf $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/management/tomcat6.conf
install -D packaging/debian/init/cloud-management $(DESTDIR)/$(SYSCONFDIR)/init.d/$(PACKAGE)-management
install -D client/target/utilities/bin/cloud-update-xenserver-licenses $(DESTDIR)/usr/bin/cloudstack-update-xenserver-licenses
# Remove configuration in /ur/share/cloudstack-management/webapps/client/WEB-INF
# This should all be in /etc/cloudstack/management
- rm $(DESTDIR)/usr/share/$(PACKAGE)-management/webapps/client/WEB-INF/classes/*.*
ln -s ../../..$(SYSCONFDIR)/$(PACKAGE)/management $(DESTDIR)/usr/share/$(PACKAGE)-management/conf
ln -s ../../../var/log/$(PACKAGE)/management $(DESTDIR)/usr/share/$(PACKAGE)-management/logs
- ln -s ../../../var/cache/$(PACKAGE)/management/temp $(DESTDIR)/usr/share/$(PACKAGE)-management/temp
- ln -s ../../../var/cache/$(PACKAGE)/management/work $(DESTDIR)/usr/share/$(PACKAGE)-management/work
install -d -m0755 debian/$(PACKAGE)-management/lib/systemd/system
- install -m0644 packaging/systemd/$(PACKAGE)-management.service.ubuntu debian/$(PACKAGE)-management/lib/systemd/system/$(PACKAGE)-management.service
- install -m0644 packaging/systemd/$(PACKAGE)-management.default.ubuntu $(DESTDIR)/$(SYSCONFDIR)/default/$(PACKAGE)-management
+ install -m0644 packaging/systemd/$(PACKAGE)-management.service debian/$(PACKAGE)-management/lib/systemd/system/$(PACKAGE)-management.service
+ install -m0644 packaging/systemd/$(PACKAGE)-management.default $(DESTDIR)/$(SYSCONFDIR)/default/$(PACKAGE)-management
# cloudstack-common
mkdir -p $(DESTDIR)/usr/share/$(PACKAGE)-common
@@ -153,5 +149,8 @@ override_dh_installinit:
override_dh_systemd_enable:
dh_systemd_enable -pcloudstack-management -pcloudstack-agent -pcloudstack-usage
+override_dh_strip_nondeterminism:
+ # Disable dh_strip_nondeterminism to speed up the build
+
override_dh_installdocs:
dh_installdocs -A tools/whisker/LICENSE tools/whisker/NOTICE INSTALL.md
diff --git a/developer/developer-prefill.sql b/developer/developer-prefill.sql
index 3fd3a1bb93d..cc67748b8dd 100644
--- a/developer/developer-prefill.sql
+++ b/developer/developer-prefill.sql
@@ -114,15 +114,16 @@ INSERT INTO `cloud`.`configuration` (category, instance, component, name, value)
VALUES ('Advanced', 'DEFAULT', 'management-server',
'ping.timeout', '1.5');
-INSERT INTO `cloud`.`configuration` (category, instance, component, name, value)
- VALUES ('Advanced', 'DEFAULT', 'management-server',
- 'outofbandmanagement.sync.interval', '1000');
-
-- Enable dynamic RBAC by default for fresh deployments
INSERT INTO `cloud`.`configuration` (category, instance, component, name, value)
VALUES ('Advanced', 'DEFAULT', 'RoleService',
'dynamic.apichecker.enabled', 'true');
+-- Enable RootCA auth strictness for fresh deployments
+INSERT INTO `cloud`.`configuration` (category, instance, component, name, value)
+ VALUES ('Advanced', 'DEFAULT', 'RootCAProvider',
+ 'ca.plugin.root.auth.strictness', 'true');
+
-- Add developer configuration entry; allows management server to be run as a user other than "cloud"
INSERT INTO `cloud`.`configuration` (category, instance, component, name, value)
VALUES ('Advanced', 'DEFAULT', 'management-server',
diff --git a/developer/pom.xml b/developer/pom.xml
index 128ae17fc1b..cf2af4febc1 100644
--- a/developer/pom.xml
+++ b/developer/pom.xml
@@ -18,7 +18,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
diff --git a/engine/api/pom.xml b/engine/api/pom.xml
index fa10d6ccbbd..e11d70e25e9 100644
--- a/engine/api/pom.xml
+++ b/engine/api/pom.xml
@@ -16,7 +16,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
@@ -35,21 +35,6 @@
<artifactId>cloud-api</artifactId>
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>org.apache.cxf</groupId>
- <artifactId>cxf-bundle-jaxrs</artifactId>
- <version>2.7.18</version>
- <exclusions>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-server</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.sun.xml.bind</groupId>
- <artifactId>jaxb-impl</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-framework-rest</artifactId>
diff --git a/engine/api/src/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java b/engine/api/src/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java
index b59c9ca5b4b..1d1bc4e4c49 100644
--- a/engine/api/src/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java
+++ b/engine/api/src/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java
@@ -60,21 +60,32 @@
*
*/
public interface NetworkOrchestrationService {
- static final String NetworkLockTimeoutCK = "network.lock.timeout";
- static final String GuestDomainSuffixCK = "guest.domain.suffix";
- static final String NetworkThrottlingRateCK = "network.throttling.rate";
- static final String MinVRVersionCK = "minreq.sysvmtemplate.version";
+ String NetworkLockTimeoutCK = "network.lock.timeout";
+ String GuestDomainSuffixCK = "guest.domain.suffix";
+ String NetworkThrottlingRateCK = "network.throttling.rate";
+ String MinVRVersionCK = "minreq.sysvmtemplate.version";
- static final ConfigKey<String> MinVRVersion = new ConfigKey<String>(String.class, MinVRVersionCK, "Advanced", "4.10.0",
+ ConfigKey<String> MinVRVersion = new ConfigKey<String>(String.class, MinVRVersionCK, "Advanced", "4.10.0",
"What version should the Virtual Routers report", true, ConfigKey.Scope.Zone, null);
- static final ConfigKey<Integer> NetworkLockTimeout = new ConfigKey<Integer>(Integer.class, NetworkLockTimeoutCK, "Network", "600",
+ ConfigKey<Integer> NetworkLockTimeout = new ConfigKey<Integer>(Integer.class, NetworkLockTimeoutCK, "Network", "600",
"Lock wait timeout (seconds) while implementing network", true, Scope.Global, null);
- static final ConfigKey<String> GuestDomainSuffix = new ConfigKey<String>(String.class, GuestDomainSuffixCK, "Network", "cloud.internal",
+
+ ConfigKey<String> GuestDomainSuffix = new ConfigKey<String>(String.class, GuestDomainSuffixCK, "Network", "cloud.internal",
"Default domain name for vms inside virtualized networks fronted by router", true, ConfigKey.Scope.Zone, null);
- static final ConfigKey<Integer> NetworkThrottlingRate = new ConfigKey<Integer>("Network", Integer.class, NetworkThrottlingRateCK, "200",
+
+ ConfigKey<Integer> NetworkThrottlingRate = new ConfigKey<Integer>("Network", Integer.class, NetworkThrottlingRateCK, "200",
"Default data transfer rate in megabits per second allowed in network.", true, ConfigKey.Scope.Zone);
+ ConfigKey<Boolean> PromiscuousMode = new ConfigKey<Boolean>("Advanced", Boolean.class, "network.promiscuous.mode", "false",
+ "Whether to allow or deny promiscuous mode on nics for applicable network elements such as for vswitch/dvswitch portgroups.", true);
+
+ ConfigKey<Boolean> MacAddressChanges = new ConfigKey<Boolean>("Advanced", Boolean.class, "network.mac.address.changes", "true",
+ "Whether to allow or deny mac address changes on nics for applicable network elements such as for vswitch/dvswitch porgroups.", true);
+
+ ConfigKey<Boolean> ForgedTransmits = new ConfigKey<Boolean>("Advanced", Boolean.class, "network.forged.transmits", "true",
+ "Whether to allow or deny forged transmits on nics for applicable network elements such as for vswitch/dvswitch portgroups.", true);
+
List<? extends Network> setupNetwork(Account owner, NetworkOffering offering, DeploymentPlan plan, String name, String displayText, boolean isDefault)
throws ConcurrentOperationException;
@@ -96,6 +107,8 @@ void prepare(VirtualMachineProfile profile, DeployDestination dest, ReservationC
List<NicProfile> getNicProfiles(VirtualMachine vm);
+ Map<String, String> getSystemVMAccessDetails(VirtualMachine vm);
+
Pair<? extends NetworkGuru, ? extends Network> implementNetwork(long networkId, DeployDestination dest, ReservationContext context)
throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException;
@@ -132,9 +145,9 @@ void prepare(VirtualMachineProfile profile, DeployDestination dest, ReservationC
boolean destroyNetwork(long networkId, ReservationContext context, boolean forced);
- Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, String networkDomain, Account owner,
- Long domainId, PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String ip6Gateway, String ip6Cidr,
- Boolean displayNetworkEnabled, String isolatedPvlan) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException;
+ Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, boolean bypassVlanOverlapCheck, String networkDomain, Account owner,
+ Long domainId, PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String ip6Gateway, String ip6Cidr,
+ Boolean displayNetworkEnabled, String isolatedPvlan) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException;
UserDataServiceProvider getPasswordResetProvider(Network network);
@@ -176,6 +189,11 @@ NicProfile prepareNic(VirtualMachineProfile vmProfile, DeployDestination dest, R
throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException, ConcurrentOperationException, InsufficientCapacityException,
ResourceUnavailableException;
+ /**
+ * Removes the provided nic from the given vm
+ * @param vm
+ * @param nic
+ */
void removeNic(VirtualMachineProfile vm, Nic nic);
/**
diff --git a/engine/api/src/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java b/engine/api/src/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java
index 3522c1b97d9..451995fc71d 100644
--- a/engine/api/src/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java
+++ b/engine/api/src/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java
@@ -57,20 +57,22 @@
*/
public interface VolumeOrchestrationService {
- static final ConfigKey<Long> CustomDiskOfferingMinSize = new ConfigKey<Long>("Advanced",
+ ConfigKey<Long> CustomDiskOfferingMinSize = new ConfigKey<Long>("Advanced",
Long.class,
"custom.diskoffering.size.min",
"1",
"Minimum size in GB for custom disk offering.",
true
);
- static final ConfigKey<Long> CustomDiskOfferingMaxSize = new ConfigKey<Long>("Advanced",
+
+ ConfigKey<Long> CustomDiskOfferingMaxSize = new ConfigKey<Long>("Advanced",
Long.class,
"custom.diskoffering.size.max",
"1024",
"Maximum size in GB for custom disk offering.",
true
);
+
VolumeInfo moveVolume(VolumeInfo volume, long destPoolDcId, Long destPoolPodId, Long destPoolClusterId, HypervisorType dataDiskHyperType)
throws ConcurrentOperationException, StorageUnavailableException;
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotInfo.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotInfo.java
index 0f05ca186f3..5541b362547 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotInfo.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotInfo.java
@@ -31,6 +31,10 @@
Object getPayload();
+ void setFullBackup(Boolean fullBackup);
+
+ Boolean getFullBackup();
+
Long getDataCenterId();
ObjectInDataStoreStateMachine.State getStatus();
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotService.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotService.java
index 322de77503a..053e0cdd134 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotService.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotService.java
@@ -17,6 +17,8 @@
package org.apache.cloudstack.engine.subsystem.api.storage;
+import com.cloud.storage.Snapshot.Event;
+
public interface SnapshotService {
SnapshotResult takeSnapshot(SnapshotInfo snapshot);
@@ -29,4 +31,8 @@
void syncVolumeSnapshotsToRegionStore(long volumeId, DataStore store);
void cleanupVolumeDuringSnapshotFailure(Long volumeId, Long snapshotId);
+
+ void processEventOnSnapshotObject(SnapshotInfo snapshot, Event event);
+
+ void cleanupOnSnapshotBackupFailure(SnapshotInfo snapshot);
}
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotStrategy.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotStrategy.java
index fbf60041ac9..62c4c20ec7b 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotStrategy.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotStrategy.java
@@ -19,6 +19,7 @@
import com.cloud.storage.Snapshot;
public interface SnapshotStrategy {
+
enum SnapshotOperation {
TAKE, BACKUP, DELETE, REVERT
}
@@ -32,4 +33,6 @@
boolean revertSnapshot(SnapshotInfo snapshot);
StrategyPriority canHandle(Snapshot snapshot, SnapshotOperation op);
+
+ void postSnapshotCreation(SnapshotInfo snapshot);
}
diff --git a/engine/components-api/pom.xml b/engine/components-api/pom.xml
index 27013d44528..5b5c7b3ab0b 100644
--- a/engine/components-api/pom.xml
+++ b/engine/components-api/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/engine/components-api/src/com/cloud/agent/AgentManager.java b/engine/components-api/src/com/cloud/agent/AgentManager.java
index 244772d67d0..933c3eaef99 100644
--- a/engine/components-api/src/com/cloud/agent/AgentManager.java
+++ b/engine/components-api/src/com/cloud/agent/AgentManager.java
@@ -137,6 +137,8 @@
void disconnectWithoutInvestigation(long hostId, Status.Event event);
+ void disconnectWithInvestigation(long hostId, Status.Event event);
+
public void pullAgentToMaintenance(long hostId);
public void pullAgentOutMaintenance(long hostId);
diff --git a/engine/components-api/src/com/cloud/configuration/ConfigurationManager.java b/engine/components-api/src/com/cloud/configuration/ConfigurationManager.java
index 46be654f581..eee159523cb 100644
--- a/engine/components-api/src/com/cloud/configuration/ConfigurationManager.java
+++ b/engine/components-api/src/com/cloud/configuration/ConfigurationManager.java
@@ -214,7 +214,7 @@ NetworkOfferingVO createNetworkOffering(String name, String displayText, Traffic
Map<NetworkOffering.Detail, String> details, boolean egressDefaultPolicy, Integer maxconn, boolean enableKeepAlive);
Vlan createVlanAndPublicIpRange(long zoneId, long networkId, long physicalNetworkId, boolean forVirtualNetwork, Long podId, String startIP, String endIP,
- String vlanGateway, String vlanNetmask, String vlanId, Domain domain, Account vlanOwner, String startIPv6, String endIPv6, String vlanIp6Gateway, String vlanIp6Cidr)
+ String vlanGateway, String vlanNetmask, String vlanId, boolean bypassVlanOverlapCheck, Domain domain, Account vlanOwner, String startIPv6, String endIPv6, String vlanIp6Gateway, String vlanIp6Cidr)
throws InsufficientCapacityException, ConcurrentOperationException, InvalidParameterValueException;
void createDefaultSystemNetworks(long zoneId) throws ConcurrentOperationException;
diff --git a/engine/components-api/src/com/cloud/network/IpAddressManager.java b/engine/components-api/src/com/cloud/network/IpAddressManager.java
index 0ab5cccb78b..d469cbac62b 100644
--- a/engine/components-api/src/com/cloud/network/IpAddressManager.java
+++ b/engine/components-api/src/com/cloud/network/IpAddressManager.java
@@ -18,7 +18,7 @@
import java.util.List;
-import com.cloud.utils.db.DB;
+import org.apache.cloudstack.api.response.AcquirePodIpCmdResponse;
import org.apache.cloudstack.framework.config.ConfigKey;
import com.cloud.dc.DataCenter;
@@ -34,16 +34,18 @@
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.StaticNat;
import com.cloud.user.Account;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.NicProfile;
import com.cloud.vm.VirtualMachineProfile;
public interface IpAddressManager {
- static final String UseSystemPublicIpsCK = "use.system.public.ips";
- static final ConfigKey<Boolean> UseSystemPublicIps = new ConfigKey<Boolean>("Advanced", Boolean.class, UseSystemPublicIpsCK, "true",
- "If true, when account has dedicated public ip range(s), once the ips dedicated to the account have been consumed ips will be acquired from the system pool",
- true, ConfigKey.Scope.Account);
+ String UseSystemPublicIpsCK = "use.system.public.ips";
+ ConfigKey<Boolean> UseSystemPublicIps = new ConfigKey<Boolean>("Advanced", Boolean.class, UseSystemPublicIpsCK, "true",
+ "If true, when account has dedicated public ip range(s), once the ips dedicated to the account have been consumed ips will be acquired from the system pool",
+ true, ConfigKey.Scope.Account);
- static final ConfigKey<Boolean> RulesContinueOnError = new ConfigKey<Boolean>("Advanced", Boolean.class, "network.rule.delete.ignoreerror", "true",
+ ConfigKey<Boolean> RulesContinueOnError = new ConfigKey<Boolean>("Advanced", Boolean.class, "network.rule.delete.ignoreerror", "true",
"When true, ip address delete (ipassoc) failures are ignored", true);
/**
@@ -51,58 +53,55 @@
*
* @param dcId
* @param podId
- * TODO
* @param owner
* @param type
* @param networkId
* @param requestedIp
- * TODO
- * @param allocatedBy
- * TODO
+ * @param isSystem
* @return
* @throws InsufficientAddressCapacityException
*/
PublicIp assignPublicIpAddress(long dcId, Long podId, Account owner, VlanType type, Long networkId, String requestedIp, boolean isSystem)
- throws InsufficientAddressCapacityException;
+ throws InsufficientAddressCapacityException;
/**
* Do all of the work of releasing public ip addresses. Note that if this method fails, there can be side effects.
*
* @param userId
* @param caller
- * TODO
- * @param IpAddress
+ * @param caller
* @return true if it did; false if it didn't
*/
boolean disassociatePublicIpAddress(long id, long userId, Account caller);
boolean applyRules(List<? extends FirewallRule> rules, FirewallRule.Purpose purpose, NetworkRuleApplier applier, boolean continueOnError)
- throws ResourceUnavailableException;
+ throws ResourceUnavailableException;
/**
- * @throws ResourceAllocationException TODO
- * @throws InsufficientCapacityException
- * Associates an ip address list to an account. The list of ip addresses are all addresses associated
- * with the
- * given vlan id.
* @param userId
* @param accountId
* @param zoneId
* @param vlanId
- * @throws InsufficientAddressCapacityException
- * @throws
+ * @param guestNetwork
+ * @throws InsufficientCapacityException
+ * @throws ConcurrentOperationException
+ * @throws ResourceUnavailableException
+ * @throws ResourceAllocationException
+ * Associates an ip address list to an account. The list of ip addresses are all addresses associated
+ * with the
+ * given vlan id.
*/
boolean associateIpAddressListToAccount(long userId, long accountId, long zoneId, Long vlanId, Network guestNetwork) throws InsufficientCapacityException,
- ConcurrentOperationException, ResourceUnavailableException, ResourceAllocationException;
+ ConcurrentOperationException, ResourceUnavailableException, ResourceAllocationException;
boolean applyIpAssociations(Network network, boolean continueOnError) throws ResourceUnavailableException;
boolean applyIpAssociations(Network network, boolean rulesRevoked, boolean continueOnError, List<? extends PublicIpAddress> publicIps)
- throws ResourceUnavailableException;
+ throws ResourceUnavailableException;
IPAddressVO markIpAsUnavailable(long addrId);
- public String acquireGuestIpAddress(Network network, String requestedIp);
+ String acquireGuestIpAddress(Network network, String requestedIp);
boolean applyStaticNats(List<? extends StaticNat> staticNats, boolean continueOnError, boolean forRevoke) throws ResourceUnavailableException;
@@ -111,7 +110,7 @@ boolean applyIpAssociations(Network network, boolean rulesRevoked, boolean conti
boolean handleSystemIpRelease(IpAddress ip);
void allocateDirectIp(NicProfile nic, DataCenter dc, VirtualMachineProfile vm, Network network, String requestedIpv4, String requestedIpv6)
- throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException;
+ throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException;
/**
* @param owner
@@ -123,28 +122,34 @@ void allocateDirectIp(NicProfile nic, DataCenter dc, VirtualMachineProfile vm, N
PublicIp assignSourceNatIpAddressToGuestNetwork(Account owner, Network guestNetwork) throws InsufficientAddressCapacityException, ConcurrentOperationException;
/**
+ *
* @param ipAddrId
* @param networkId
- * @param releaseOnFailure TODO
+ * @param releaseOnFailure
+ * @return
+ * @throws ResourceAllocationException
+ * @throws ResourceUnavailableException
+ * @throws InsufficientAddressCapacityException
+ * @throws ConcurrentOperationException
*/
IPAddressVO associateIPToGuestNetwork(long ipAddrId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException, ResourceUnavailableException,
- InsufficientAddressCapacityException, ConcurrentOperationException;
+ InsufficientAddressCapacityException, ConcurrentOperationException;
IpAddress allocatePortableIp(Account ipOwner, Account caller, long dcId, Long networkId, Long vpcID) throws ConcurrentOperationException,
- ResourceAllocationException, InsufficientAddressCapacityException;
+ ResourceAllocationException, InsufficientAddressCapacityException;
boolean releasePortableIpAddress(long addrId);
IPAddressVO associatePortableIPToGuestNetwork(long ipAddrId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException,
- ResourceUnavailableException, InsufficientAddressCapacityException, ConcurrentOperationException;
+ ResourceUnavailableException, InsufficientAddressCapacityException, ConcurrentOperationException;
IPAddressVO disassociatePortableIPToGuestNetwork(long ipAddrId, long networkId) throws ResourceAllocationException, ResourceUnavailableException,
- InsufficientAddressCapacityException, ConcurrentOperationException;
+ InsufficientAddressCapacityException, ConcurrentOperationException;
boolean isPortableIpTransferableFromNetwork(long ipAddrId, long networkId);
void transferPortableIP(long ipAddrId, long currentNetworkId, long newNetworkId) throws ResourceAllocationException, ResourceUnavailableException,
- InsufficientAddressCapacityException, ConcurrentOperationException;;
+ InsufficientAddressCapacityException, ConcurrentOperationException;;
/**
* @param addr
@@ -162,22 +167,26 @@ void transferPortableIP(long ipAddrId, long currentNetworkId, long newNetworkId)
* @throws InsufficientAddressCapacityException
*/
PublicIp assignDedicateIpAddress(Account owner, Long guestNtwkId, Long vpcId, long dcId, boolean isSourceNat) throws ConcurrentOperationException,
- InsufficientAddressCapacityException;
+ InsufficientAddressCapacityException;
IpAddress allocateIp(Account ipOwner, boolean isSystem, Account caller, long callerId, DataCenter zone, Boolean displayIp) throws ConcurrentOperationException,
- ResourceAllocationException, InsufficientAddressCapacityException;
+ ResourceAllocationException, InsufficientAddressCapacityException;
PublicIp assignPublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List<Long> vlanDbIds, Long networkId, String requestedIp,
- boolean isSystem) throws InsufficientAddressCapacityException;
+ boolean isSystem) throws InsufficientAddressCapacityException;
@DB
void allocateNicValues(NicProfile nic, DataCenter dc, VirtualMachineProfile vm, Network network, String requestedIpv4,
- String requestedIpv6) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException;
+ String requestedIpv6) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException;
int getRuleCountForIp(Long addressId, FirewallRule.Purpose purpose, FirewallRule.State state);
- public String allocateGuestIP(Network network, String requestedIp) throws InsufficientAddressCapacityException;
+ String allocateGuestIP(Network network, String requestedIp) throws InsufficientAddressCapacityException;
String allocatePublicIpForGuestNic(Network network, Long podId, Account ipOwner, String requestedIp) throws InsufficientAddressCapacityException;
+ AcquirePodIpCmdResponse allocatePodIp(String zoneId, String podId) throws ConcurrentOperationException, ResourceAllocationException;
+
+ void releasePodIp(Long id) throws CloudRuntimeException;
}
+
diff --git a/engine/components-api/src/com/cloud/network/vpc/VpcManager.java b/engine/components-api/src/com/cloud/network/vpc/VpcManager.java
index 8539871e48b..28ad0524a2a 100644
--- a/engine/components-api/src/com/cloud/network/vpc/VpcManager.java
+++ b/engine/components-api/src/com/cloud/network/vpc/VpcManager.java
@@ -165,4 +165,11 @@
validateNtwkOffForNtwkInVpc(Long networkId, long newNtwkOffId, String newCidr, String newNetworkDomain, Vpc vpc, String gateway, Account networkOwner, Long aclId);
List<PrivateGateway> getVpcPrivateGateways(long vpcId);
+
+ /**
+ * Checks if the specified offering needs a public src nat ip or not.
+ * @param vpcOfferingId
+ * @return
+ */
+ boolean isSrcNatIpRequired(long vpcOfferingId);
}
diff --git a/engine/components-api/src/com/cloud/resource/ResourceManager.java b/engine/components-api/src/com/cloud/resource/ResourceManager.java
index 7783fa139a9..d96434b0838 100755
--- a/engine/components-api/src/com/cloud/resource/ResourceManager.java
+++ b/engine/components-api/src/com/cloud/resource/ResourceManager.java
@@ -99,6 +99,8 @@
public List<HostVO> listAllHosts(final Host.Type type, final Long clusterId, final Long podId, final long dcId);
+ public List<HostVO> listAllUpHosts(Host.Type type, Long clusterId, Long podId, long dcId);
+
public List<HostVO> listAllHostsInCluster(long clusterId);
public List<HostVO> listHostsInClusterByStatus(long clusterId, Status status);
diff --git a/engine/components-api/src/com/cloud/storage/StorageManager.java b/engine/components-api/src/com/cloud/storage/StorageManager.java
index 129f6b1d354..d314fb33bd6 100644
--- a/engine/components-api/src/com/cloud/storage/StorageManager.java
+++ b/engine/components-api/src/com/cloud/storage/StorageManager.java
@@ -50,6 +50,8 @@
"Determines how long (in seconds) to wait before actually expunging destroyed volumes. The default value = the default value of storage.cleanup.interval.", false, ConfigKey.Scope.Global, null);
static final ConfigKey<Boolean> StorageCleanupEnabled = new ConfigKey<Boolean>(Boolean.class, "storage.cleanup.enabled", "Advanced", "true",
"Enables/disables the storage cleanup thread.", false, ConfigKey.Scope.Global, null);
+ static final ConfigKey<Boolean> TemplateCleanupEnabled = new ConfigKey<Boolean>(Boolean.class, "storage.template.cleanup.enabled", "Storage", "true",
+ "Enable/disable template cleanup activity, only take effect when overall storage cleanup is enabled", false, ConfigKey.Scope.Global, null);
/**
* Returns a comma separated list of tags for the specified storage pool
diff --git a/engine/components-api/src/com/cloud/template/TemplateManager.java b/engine/components-api/src/com/cloud/template/TemplateManager.java
index 5b2d64ad5a3..68c3b585692 100644
--- a/engine/components-api/src/com/cloud/template/TemplateManager.java
+++ b/engine/components-api/src/com/cloud/template/TemplateManager.java
@@ -115,7 +115,7 @@
DataStore getImageStore(String storeUuid, Long zoneId);
- String getChecksum(DataStore store, String templatePath);
+ String getChecksum(DataStore store, String templatePath, String algorithm);
List<DataStore> getImageStoreByTemplate(long templateId, Long zoneId);
diff --git a/engine/components-api/src/com/cloud/vm/VmWorkTakeVolumeSnapshot.java b/engine/components-api/src/com/cloud/vm/VmWorkTakeVolumeSnapshot.java
index 495dc4638fb..6d6264406de 100644
--- a/engine/components-api/src/com/cloud/vm/VmWorkTakeVolumeSnapshot.java
+++ b/engine/components-api/src/com/cloud/vm/VmWorkTakeVolumeSnapshot.java
@@ -27,15 +27,17 @@
private Long snapshotId;
private boolean quiesceVm;
private Snapshot.LocationType locationType;
+ private boolean asyncBackup;
public VmWorkTakeVolumeSnapshot(long userId, long accountId, long vmId, String handlerName,
- Long volumeId, Long policyId, Long snapshotId, boolean quiesceVm, Snapshot.LocationType locationType) {
+ Long volumeId, Long policyId, Long snapshotId, boolean quiesceVm, Snapshot.LocationType locationType, boolean asyncBackup) {
super(userId, accountId, vmId, handlerName);
this.volumeId = volumeId;
this.policyId = policyId;
this.snapshotId = snapshotId;
this.quiesceVm = quiesceVm;
this.locationType = locationType;
+ this.asyncBackup = asyncBackup;
}
public Long getVolumeId() {
@@ -55,4 +57,8 @@ public boolean isQuiesceVm() {
}
public Snapshot.LocationType getLocationType() { return locationType; }
+
+ public boolean isAsyncBackup() {
+ return asyncBackup;
+ }
}
diff --git a/engine/components-api/src/com/cloud/vm/snapshot/VMSnapshotManager.java b/engine/components-api/src/com/cloud/vm/snapshot/VMSnapshotManager.java
index ce8a818ac1d..82456004cc3 100644
--- a/engine/components-api/src/com/cloud/vm/snapshot/VMSnapshotManager.java
+++ b/engine/components-api/src/com/cloud/vm/snapshot/VMSnapshotManager.java
@@ -19,12 +19,18 @@
import java.util.List;
+import org.apache.cloudstack.framework.config.ConfigKey;
+
import com.cloud.agent.api.RestoreVMSnapshotCommand;
import com.cloud.utils.component.Manager;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
public interface VMSnapshotManager extends VMSnapshotService, Manager {
+
+ static final ConfigKey<Integer> VMSnapshotExpireInterval = new ConfigKey<Integer>("Advanced", Integer.class, "vmsnapshot.expire.interval", "-1",
+ "VM Snapshot expire interval in hours", true, ConfigKey.Scope.Account);
+
public static final int VMSNAPSHOTMAX = 10;
/**
diff --git a/engine/network/pom.xml b/engine/network/pom.xml
index 34b1d67bc63..178130ec04d 100644
--- a/engine/network/pom.xml
+++ b/engine/network/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/engine/orchestration/pom.xml b/engine/orchestration/pom.xml
index 4487b6cada3..7d747058391 100755
--- a/engine/orchestration/pom.xml
+++ b/engine/orchestration/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/engine/orchestration/src/com/cloud/agent/manager/AgentAttache.java b/engine/orchestration/src/com/cloud/agent/manager/AgentAttache.java
index d5ec9009838..a3838e1e6ef 100644
--- a/engine/orchestration/src/com/cloud/agent/manager/AgentAttache.java
+++ b/engine/orchestration/src/com/cloud/agent/manager/AgentAttache.java
@@ -31,6 +31,7 @@
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
+import com.cloud.agent.api.ModifySshKeysCommand;
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.log4j.Logger;
@@ -114,7 +115,7 @@ public int compare(final Object o1, final Object o2) {
StopCommand.class.toString(), CheckVirtualMachineCommand.class.toString(), PingTestCommand.class.toString(), CheckHealthCommand.class.toString(),
ReadyCommand.class.toString(), ShutdownCommand.class.toString(), SetupCommand.class.toString(),
CleanupNetworkRulesCmd.class.toString(), CheckNetworkCommand.class.toString(), PvlanSetupCommand.class.toString(), CheckOnHostCommand.class.toString(),
- ModifyTargetsCommand.class.toString() };
+ ModifyTargetsCommand.class.toString(), ModifySshKeysCommand.class.toString()};
protected final static String[] s_commandsNotAllowedInConnectingMode = new String[] { StartCommand.class.toString(), CreateCommand.class.toString() };
static {
Arrays.sort(s_commandsAllowedInMaintenanceMode);
diff --git a/engine/orchestration/src/com/cloud/agent/manager/AgentManagerImpl.java b/engine/orchestration/src/com/cloud/agent/manager/AgentManagerImpl.java
index 597ea6733e9..325f3ec739f 100644
--- a/engine/orchestration/src/com/cloud/agent/manager/AgentManagerImpl.java
+++ b/engine/orchestration/src/com/cloud/agent/manager/AgentManagerImpl.java
@@ -37,6 +37,7 @@
import javax.inject.Inject;
import javax.naming.ConfigurationException;
+import org.apache.cloudstack.ca.CAManager;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
@@ -134,6 +135,8 @@
protected int _monitorId = 0;
private final Lock _agentStatusLock = new ReentrantLock();
+ @Inject
+ protected CAManager caService;
@Inject
protected EntityManager _entityMgr;
@@ -223,7 +226,7 @@ public boolean configure(final String name, final Map<String, Object> params) th
// allow core threads to time out even when there are no items in the queue
_connectExecutor.allowCoreThreadTimeOut(true);
- _connection = new NioServer("AgentManager", Port.value(), Workers.value() + 10, this);
+ _connection = new NioServer("AgentManager", Port.value(), Workers.value() + 10, this, caService);
s_logger.info("Listening on " + Port.value() + " with " + Workers.value() + " workers");
// executes all agent commands other than cron and ping
@@ -813,6 +816,7 @@ protected boolean handleDisconnectWithoutInvestigation(final AgentAttache attach
s_logger.debug("The next status of agent " + hostId + "is " + nextStatus + ", current status is " + currentStatus);
}
}
+ caService.purgeHostCertificate(host);
}
if (s_logger.isDebugEnabled()) {
diff --git a/engine/orchestration/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java b/engine/orchestration/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java
index 9239adc0911..2ebfeb5dd67 100644
--- a/engine/orchestration/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java
+++ b/engine/orchestration/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java
@@ -42,6 +42,7 @@
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
+import org.apache.cloudstack.ca.CAManager;
import org.apache.cloudstack.framework.config.ConfigDepot;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
@@ -49,6 +50,8 @@
import org.apache.cloudstack.managed.context.ManagedContextTimerTask;
import org.apache.cloudstack.utils.identity.ManagementServerNode;
import org.apache.cloudstack.utils.security.SSLUtils;
+import org.apache.cloudstack.ha.dao.HAConfigDao;
+import org.apache.cloudstack.outofbandmanagement.dao.OutOfBandManagementDao;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
@@ -120,6 +123,12 @@
ConfigurationDao _configDao;
@Inject
ConfigDepot _configDepot;
+ @Inject
+ private OutOfBandManagementDao outOfBandManagementDao;
+ @Inject
+ private HAConfigDao haConfigDao;
+ @Inject
+ private CAManager caService;
protected ClusteredAgentManagerImpl() {
super();
@@ -164,6 +173,7 @@ public boolean start() {
// Schedule tasks for agent rebalancing
if (isAgentRebalanceEnabled()) {
+ cleanupTransferMap(_nodeId);
s_transferExecutor.scheduleAtFixedRate(getAgentRebalanceScanTask(), 60000, 60000, TimeUnit.MILLISECONDS);
s_transferExecutor.scheduleAtFixedRate(getTransferScanTask(), 60000, ClusteredAgentRebalanceService.DEFAULT_TRANSFER_CHECK_INTERVAL, TimeUnit.MILLISECONDS);
}
@@ -491,6 +501,7 @@ public SocketChannel connectToPeer(final String peerName, final SocketChannel pr
}
final String ip = ms.getServiceIP();
InetAddress addr;
+ int port = Port.value();
try {
addr = InetAddress.getByName(ip);
} catch (final UnknownHostException e) {
@@ -498,21 +509,21 @@ public SocketChannel connectToPeer(final String peerName, final SocketChannel pr
}
SocketChannel ch1 = null;
try {
- ch1 = SocketChannel.open(new InetSocketAddress(addr, Port.value()));
+ ch1 = SocketChannel.open(new InetSocketAddress(addr, port));
ch1.configureBlocking(false);
ch1.socket().setKeepAlive(true);
ch1.socket().setSoTimeout(60 * 1000);
try {
- final SSLContext sslContext = Link.initSSLContext(true);
- sslEngine = sslContext.createSSLEngine(ip, Port.value());
+ SSLContext sslContext = Link.initManagementSSLContext(caService);
+ sslEngine = sslContext.createSSLEngine(ip, port);
sslEngine.setUseClientMode(true);
sslEngine.setEnabledProtocols(SSLUtils.getSupportedProtocols(sslEngine.getEnabledProtocols()));
sslEngine.beginHandshake();
if (!Link.doHandshake(ch1, sslEngine, true)) {
ch1.close();
- throw new IOException("SSL handshake failed!");
+ throw new IOException(String.format("SSL: Handshake failed with peer management server '%s' on %s:%d ", peerName, ip, port));
}
- s_logger.info("SSL: Handshake done");
+ s_logger.info(String.format("SSL: Handshake done with peer management server '%s' on %s:%d ", peerName, ip, port));
} catch (final Exception e) {
ch1.close();
throw new IOException("SSL: Fail to init SSL! " + e);
@@ -524,10 +535,12 @@ public SocketChannel connectToPeer(final String peerName, final SocketChannel pr
_sslEngines.put(peerName, sslEngine);
return ch1;
} catch (final IOException e) {
- try {
- ch1.close();
- } catch (final IOException ex) {
- s_logger.error("failed to close failed peer socket: " + ex);
+ if (ch1 != null) {
+ try {
+ ch1.close();
+ } catch (final IOException ex) {
+ s_logger.error("failed to close failed peer socket: " + ex);
+ }
}
s_logger.warn("Unable to connect to peer management server: " + peerName + ", ip: " + ip + " due to " + e.getMessage(), e);
return null;
@@ -736,7 +749,8 @@ public void onManagementNodeLeft(final List<? extends ManagementServerHost> node
s_logger.info("Marking hosts as disconnected on Management server" + vo.getMsid());
final long lastPing = (System.currentTimeMillis() >> 10) - getTimeout();
_hostDao.markHostsAsDisconnected(vo.getMsid(), lastPing);
- outOfBandManagementDao.expireOutOfBandManagementOwnershipByServer(vo.getMsid());
+ outOfBandManagementDao.expireServerOwnership(vo.getMsid());
+ haConfigDao.expireServerOwnership(vo.getMsid());
s_logger.info("Deleting entries from op_host_transfer table for Management server " + vo.getMsid());
cleanupTransferMap(vo.getMsid());
}
diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
index 8cc8de12433..f684cbfe881 100755
--- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -22,6 +22,7 @@
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
@@ -39,12 +40,14 @@
import com.cloud.agent.api.AttachOrDettachConfigDriveCommand;
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
+import org.apache.cloudstack.ca.CAManager;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
+import org.apache.cloudstack.framework.ca.Certificate;
import org.apache.cloudstack.framework.config.ConfigDepot;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
@@ -97,6 +100,7 @@
import com.cloud.agent.api.UnPlugNicAnswer;
import com.cloud.agent.api.UnPlugNicCommand;
import com.cloud.agent.api.UnregisterVMCommand;
+import com.cloud.agent.api.routing.NetworkElementCommand;
import com.cloud.agent.api.to.DiskTO;
import com.cloud.agent.api.to.GPUDeviceTO;
import com.cloud.agent.api.to.NicTO;
@@ -155,6 +159,7 @@
import com.cloud.offering.ServiceOffering;
import com.cloud.org.Cluster;
import com.cloud.resource.ResourceManager;
+import com.cloud.resource.ResourceState;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DiskOfferingVO;
@@ -205,6 +210,7 @@
import com.cloud.vm.snapshot.VMSnapshotManager;
import com.cloud.vm.snapshot.VMSnapshotVO;
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
+import com.google.common.base.Strings;
public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMachineManager, VmWorkJobHandler, Listener, Configurable {
private static final Logger s_logger = Logger.getLogger(VirtualMachineManagerImpl.class);
@@ -236,6 +242,8 @@
@Inject
protected UserVmDao _userVmDao;
@Inject
+ protected UserVmService _userVmService;
+ @Inject
protected CapacityManager _capacityMgr;
@Inject
protected NicDao _nicsDao;
@@ -282,7 +290,9 @@
@Inject
protected UserVmDetailsDao _vmDetailsDao;
@Inject
- ServiceOfferingDao _serviceOfferingDao = null;
+ protected ServiceOfferingDao _serviceOfferingDao = null;
+ @Inject
+ protected CAManager caManager;
@Inject
ConfigDepot _configDepot;
@@ -404,7 +414,8 @@ public void doInTransactionWithoutResult(final TransactionStatus status) throws
}
try {
- _networkMgr.allocate(vmProfile, auxiliaryNetworks);
+ if (!vmProfile.getBootArgs().contains("ExternalLoadBalancerVm"))
+ _networkMgr.allocate(vmProfile, auxiliaryNetworks);
} catch (final ConcurrentOperationException e) {
throw new CloudRuntimeException("Concurrent operation while trying to allocate resources for the VM", e);
}
@@ -1020,7 +1031,6 @@ public void orchestrateStart(final String vmUuid, final Map<VirtualMachineProfil
cmds.addCommand(new StartCommand(vmTO, dest.getHost(), getExecuteInSequence(vm.getHypervisorType())));
-
vmGuru.finalizeDeployment(cmds, vmProfile, dest, ctx);
work = _workDao.findById(work.getId());
@@ -1070,6 +1080,23 @@ public void orchestrateStart(final String vmUuid, final Map<VirtualMachineProfil
if (s_logger.isDebugEnabled()) {
s_logger.debug("Start completed for VM " + vm);
}
+ final Host vmHost = _hostDao.findById(destHostId);
+ if (vmHost != null && (VirtualMachine.Type.ConsoleProxy.equals(vm.getType()) ||
+ VirtualMachine.Type.SecondaryStorageVm.equals(vm.getType())) && caManager.canProvisionCertificates()) {
+ final Map<String, String> sshAccessDetails = _networkMgr.getSystemVMAccessDetails(vm);
+ final String csr = caManager.generateKeyStoreAndCsr(vmHost, sshAccessDetails);
+ if (!Strings.isNullOrEmpty(csr)) {
+ final Map<String, String> ipAddressDetails = new HashMap<>(sshAccessDetails);
+ ipAddressDetails.remove(NetworkElementCommand.ROUTER_NAME);
+ final Certificate certificate = caManager.issueCertificate(csr, Arrays.asList(vm.getHostName(), vm.getInstanceName()), new ArrayList<>(ipAddressDetails.values()), CAManager.CertValidityPeriod.value(), null);
+ final boolean result = caManager.deployCertificate(vmHost, certificate, false, sshAccessDetails);
+ if (!result) {
+ s_logger.error("Failed to setup certificate for system vm: " + vm.getInstanceName());
+ }
+ } else {
+ s_logger.error("Failed to setup keystore and generate CSR for system vm: " + vm.getInstanceName());
+ }
+ }
return;
} else {
if (s_logger.isDebugEnabled()) {
@@ -1505,6 +1532,12 @@ private void advanceStop(final VMInstanceVO vm, final boolean cleanUpEvenIfUnabl
_workDao.update(work.getId(), work);
}
return;
+ } else {
+ HostVO host = _hostDao.findById(hostId);
+ if (!cleanUpEvenIfUnableToStop && vm.getState() == State.Running && host.getResourceState() == ResourceState.PrepareForMaintenance) {
+ s_logger.debug("Host is in PrepareForMaintenance state - Stop VM operation on the VM id: " + vm.getId() + " is not allowed");
+ throw new CloudRuntimeException("Stop VM operation on the VM id: " + vm.getId() + " is not allowed as host is preparing for maintenance mode");
+ }
}
final VirtualMachineGuru vmGuru = getVmGuru(vm);
@@ -1707,17 +1740,20 @@ public void destroy(final String vmUuid, final boolean expunge) throws AgentUnav
deleteVMSnapshots(vm, expunge);
- // reload the vm object from db
- vm = _vmDao.findByUuid(vmUuid);
- try {
- if (!stateTransitTo(vm, VirtualMachine.Event.DestroyRequested, vm.getHostId())) {
- s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vm);
- throw new CloudRuntimeException("Unable to destroy " + vm);
+ Transaction.execute(new TransactionCallbackWithExceptionNoReturn<CloudRuntimeException>() {
+ public void doInTransactionWithoutResult(final TransactionStatus status) throws CloudRuntimeException {
+ VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
+ try {
+ if (!stateTransitTo(vm, VirtualMachine.Event.DestroyRequested, vm.getHostId())) {
+ s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vm);
+ throw new CloudRuntimeException("Unable to destroy " + vm);
+ }
+ } catch (final NoTransitionException e) {
+ s_logger.debug(e.getMessage());
+ throw new CloudRuntimeException("Unable to destroy " + vm, e);
+ }
}
- } catch (final NoTransitionException e) {
- s_logger.debug(e.getMessage());
- throw new CloudRuntimeException("Unable to destroy " + vm, e);
- }
+ });
}
/**
@@ -3636,6 +3672,11 @@ public boolean unplugNic(final Network network, final NicTO nic, final VirtualMa
final VMInstanceVO router = _vmDao.findById(vm.getId());
if (router.getState() == State.Running) {
+ // collect vm network statistics before unplug a nic
+ UserVmVO userVm = _userVmDao.findById(vm.getId());
+ if (userVm != null && userVm.getType() == VirtualMachine.Type.User) {
+ _userVmService.collectVmNetworkStatistics(userVm);
+ }
try {
final Commands cmds = new Commands(Command.OnError.Stop);
final UnPlugNicCommand unplugNicCmd = new UnPlugNicCommand(nic, vm.getName());
diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/datacenter/entity/api/db/EngineClusterVO.java b/engine/orchestration/src/org/apache/cloudstack/engine/datacenter/entity/api/db/EngineClusterVO.java
index 0c34e3c5285..75965fe4bd1 100644
--- a/engine/orchestration/src/org/apache/cloudstack/engine/datacenter/entity/api/db/EngineClusterVO.java
+++ b/engine/orchestration/src/org/apache/cloudstack/engine/datacenter/entity/api/db/EngineClusterVO.java
@@ -16,8 +16,16 @@
// under the License.
package org.apache.cloudstack.engine.datacenter.entity.api.db;
-import java.util.Date;
-import java.util.UUID;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.org.Cluster;
+import com.cloud.org.Grouping;
+import com.cloud.org.Managed.ManagedState;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.db.GenericDao;
+import com.cloud.utils.db.StateMachine;
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.engine.datacenter.entity.api.DataCenterResourceEntity.State;
+import org.apache.cloudstack.engine.datacenter.entity.api.DataCenterResourceEntity.State.Event;
import javax.persistence.Column;
import javax.persistence.Entity;
@@ -29,18 +37,8 @@
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
-
-import org.apache.cloudstack.api.Identity;
-import org.apache.cloudstack.engine.datacenter.entity.api.DataCenterResourceEntity.State;
-import org.apache.cloudstack.engine.datacenter.entity.api.DataCenterResourceEntity.State.Event;
-
-import com.cloud.hypervisor.Hypervisor.HypervisorType;
-import com.cloud.org.Cluster;
-import com.cloud.org.Grouping;
-import com.cloud.org.Managed.ManagedState;
-import com.cloud.utils.NumbersUtil;
-import com.cloud.utils.db.GenericDao;
-import com.cloud.utils.db.StateMachine;
+import java.util.Date;
+import java.util.UUID;
@Entity
@Table(name = "cluster")
@@ -243,4 +241,9 @@ public Date getLastUpdated() {
public State getState() {
return state;
}
+
+ @Override
+ public PartitionType partitionType() {
+ return PartitionType.Cluster;
+ }
}
diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/datacenter/entity/api/db/EngineDataCenterVO.java b/engine/orchestration/src/org/apache/cloudstack/engine/datacenter/entity/api/db/EngineDataCenterVO.java
index ca9ad50b3c1..ba967be6210 100644
--- a/engine/orchestration/src/org/apache/cloudstack/engine/datacenter/entity/api/db/EngineDataCenterVO.java
+++ b/engine/orchestration/src/org/apache/cloudstack/engine/datacenter/entity/api/db/EngineDataCenterVO.java
@@ -16,9 +16,14 @@
// under the License.
package org.apache.cloudstack.engine.datacenter.entity.api.db;
-import java.util.Date;
-import java.util.Map;
-import java.util.UUID;
+import com.cloud.network.Network.Provider;
+import com.cloud.org.Grouping;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.db.GenericDao;
+import com.cloud.utils.db.StateMachine;
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.engine.datacenter.entity.api.DataCenterResourceEntity.State;
+import org.apache.cloudstack.engine.datacenter.entity.api.DataCenterResourceEntity.State.Event;
import javax.persistence.Column;
import javax.persistence.Entity;
@@ -32,16 +37,9 @@
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
-
-import org.apache.cloudstack.api.Identity;
-import org.apache.cloudstack.engine.datacenter.entity.api.DataCenterResourceEntity.State;
-import org.apache.cloudstack.engine.datacenter.entity.api.DataCenterResourceEntity.State.Event;
-
-import com.cloud.network.Network.Provider;
-import com.cloud.org.Grouping;
-import com.cloud.utils.NumbersUtil;
-import com.cloud.utils.db.GenericDao;
-import com.cloud.utils.db.StateMachine;
+import java.util.Date;
+import java.util.Map;
+import java.util.UUID;
@Entity
@Table(name = "data_center")
@@ -501,4 +499,9 @@ public String getIp6Dns2() {
public void setIp6Dns2(String ip6Dns2) {
this.ip6Dns2 = ip6Dns2;
}
+
+ @Override
+ public PartitionType partitionType() {
+ return PartitionType.Zone;
+ }
}
diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/datacenter/entity/api/db/EngineHostVO.java b/engine/orchestration/src/org/apache/cloudstack/engine/datacenter/entity/api/db/EngineHostVO.java
index efa34dfec98..be1484f0bde 100644
--- a/engine/orchestration/src/org/apache/cloudstack/engine/datacenter/entity/api/db/EngineHostVO.java
+++ b/engine/orchestration/src/org/apache/cloudstack/engine/datacenter/entity/api/db/EngineHostVO.java
@@ -16,10 +16,16 @@
// under the License.
package org.apache.cloudstack.engine.datacenter.entity.api.db;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
+import com.cloud.host.Status;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.resource.ResourceState;
+import com.cloud.storage.Storage.StoragePoolType;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.db.GenericDao;
+import com.cloud.utils.db.StateMachine;
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.engine.datacenter.entity.api.DataCenterResourceEntity.State;
+import org.apache.cloudstack.engine.datacenter.entity.api.DataCenterResourceEntity.State.Event;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
@@ -36,18 +42,10 @@
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
-
-import org.apache.cloudstack.api.Identity;
-import org.apache.cloudstack.engine.datacenter.entity.api.DataCenterResourceEntity.State;
-import org.apache.cloudstack.engine.datacenter.entity.api.DataCenterResourceEntity.State.Event;
-
-import com.cloud.host.Status;
-import com.cloud.hypervisor.Hypervisor.HypervisorType;
-import com.cloud.resource.ResourceState;
-import com.cloud.storage.Storage.StoragePoolType;
-import com.cloud.utils.NumbersUtil;
-import com.cloud.utils.db.GenericDao;
-import com.cloud.utils.db.StateMachine;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
@Entity
@Table(name = "host")
@@ -178,6 +176,11 @@ public Long getClusterId() {
return clusterId;
}
+ @Override
+ public ResourceType resourceType() {
+ return ResourceType.Host;
+ }
+
public void setClusterId(Long clusterId) {
this.clusterId = clusterId;
}
@@ -720,6 +723,11 @@ public void setResourceState(ResourceState state) {
resourceState = state;
}
+ @Override
+ public boolean isDisabled() {
+ return (getResourceState() == ResourceState.Disabled);
+ }
+
@Override
public boolean isInMaintenanceStates() {
return (getResourceState() == ResourceState.Maintenance || getResourceState() == ResourceState.ErrorInMaintenance || getResourceState() == ResourceState.PrepareForMaintenance);
@@ -758,4 +766,9 @@ public Date getLastUpdated() {
public State getOrchestrationState() {
return orchestrationState;
}
+
+ @Override
+ public PartitionType partitionType() {
+ return PartitionType.Host;
+ }
}
diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
index 37f53302455..755fba2f74c 100644
--- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
+++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
@@ -32,18 +32,10 @@
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
+
import javax.inject.Inject;
import javax.naming.ConfigurationException;
-import com.cloud.network.dao.NetworkDetailsDao;
-import com.cloud.network.dao.RemoteAccessVpnDao;
-import com.cloud.network.dao.RemoteAccessVpnVO;
-import com.cloud.network.dao.VpnUserDao;
-import com.cloud.network.element.RedundantResource;
-import com.cloud.network.router.VirtualRouter;
-import com.cloud.vm.DomainRouterVO;
-import com.cloud.vm.dao.DomainRouterDao;
-import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.cloud.entity.api.db.VMNetworkMapVO;
@@ -58,6 +50,8 @@
import org.apache.cloudstack.framework.messagebus.PublishScope;
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.cloudstack.region.PortableIpDao;
+import org.apache.log4j.Logger;
+
import com.cloud.agent.AgentManager;
import com.cloud.agent.Listener;
import com.cloud.agent.api.AgentControlAnswer;
@@ -68,6 +62,7 @@
import com.cloud.agent.api.Command;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
+import com.cloud.agent.api.routing.NetworkElementCommand;
import com.cloud.agent.api.to.NicTO;
import com.cloud.alert.AlertManager;
import com.cloud.configuration.ConfigurationManager;
@@ -128,6 +123,7 @@
import com.cloud.network.dao.NetworkAccountDao;
import com.cloud.network.dao.NetworkAccountVO;
import com.cloud.network.dao.NetworkDao;
+import com.cloud.network.dao.NetworkDetailsDao;
import com.cloud.network.dao.NetworkDomainDao;
import com.cloud.network.dao.NetworkDomainVO;
import com.cloud.network.dao.NetworkServiceMapDao;
@@ -138,17 +134,22 @@
import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao;
import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO;
import com.cloud.network.dao.PhysicalNetworkVO;
+import com.cloud.network.dao.RemoteAccessVpnDao;
+import com.cloud.network.dao.RemoteAccessVpnVO;
+import com.cloud.network.dao.VpnUserDao;
import com.cloud.network.element.AggregatedCommandExecutor;
import com.cloud.network.element.DhcpServiceProvider;
import com.cloud.network.element.DnsServiceProvider;
import com.cloud.network.element.IpDeployer;
import com.cloud.network.element.LoadBalancingServiceProvider;
import com.cloud.network.element.NetworkElement;
+import com.cloud.network.element.RedundantResource;
import com.cloud.network.element.StaticNatServiceProvider;
import com.cloud.network.element.UserDataServiceProvider;
import com.cloud.network.guru.NetworkGuru;
import com.cloud.network.guru.NetworkGuruAdditionalFunctions;
import com.cloud.network.lb.LoadBalancingRulesManager;
+import com.cloud.network.router.VirtualRouter;
import com.cloud.network.rules.FirewallManager;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.FirewallRule.Purpose;
@@ -196,6 +197,7 @@
import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.utils.fsm.StateMachine2;
import com.cloud.utils.net.NetUtils;
+import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.Nic;
import com.cloud.vm.Nic.ReservationStrategy;
import com.cloud.vm.NicIpAlias;
@@ -208,6 +210,7 @@
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.VirtualMachineProfile;
+import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.NicIpAliasDao;
import com.cloud.vm.dao.NicIpAliasVO;
@@ -215,6 +218,7 @@
import com.cloud.vm.dao.NicSecondaryIpVO;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
+import com.google.common.base.Strings;
/**
* NetworkManagerImpl implements NetworkManager.
@@ -2015,9 +2019,9 @@ public void expungeNics(final VirtualMachineProfile vm) {
@Override
@DB
public Network createGuestNetwork(final long networkOfferingId, final String name, final String displayText, final String gateway, final String cidr, String vlanId,
- String networkDomain, final Account owner, final Long domainId, final PhysicalNetwork pNtwk, final long zoneId, final ACLType aclType, Boolean subdomainAccess,
- final Long vpcId, final String ip6Gateway, final String ip6Cidr, final Boolean isDisplayNetworkEnabled, final String isolatedPvlan)
- throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException {
+ boolean bypassVlanOverlapCheck, String networkDomain, final Account owner, final Long domainId, final PhysicalNetwork pNtwk,
+ final long zoneId, final ACLType aclType, Boolean subdomainAccess, final Long vpcId, final String ip6Gateway, final String ip6Cidr,
+ final Boolean isDisplayNetworkEnabled, final String isolatedPvlan) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException {
final NetworkOfferingVO ntwkOff = _networkOfferingDao.findById(networkOfferingId);
// this method supports only guest network creation
@@ -2134,19 +2138,19 @@ public Network createGuestNetwork(final long networkOfferingId, final String nam
}
if (vlanSpecified) {
+ URI uri = BroadcastDomainType.fromString(vlanId);
//don't allow to specify vlan tag used by physical network for dynamic vlan allocation
- if (_dcDao.findVnet(zoneId, pNtwk.getId(), vlanId).size() > 0) {
+ if (!(bypassVlanOverlapCheck && ntwkOff.getGuestType() == GuestType.Shared) && _dcDao.findVnet(zoneId, pNtwk.getId(), BroadcastDomainType.getValue(uri)).size() > 0) {
throw new InvalidParameterValueException("The VLAN tag " + vlanId + " is already being used for dynamic vlan allocation for the guest network in zone "
+ zone.getName());
}
if (! UuidUtils.validateUUID(vlanId)){
- final String uri = BroadcastDomainType.fromString(vlanId).toString();
// For Isolated networks, don't allow to create network with vlan that already exists in the zone
if (ntwkOff.getGuestType() == GuestType.Isolated) {
- if (_networksDao.countByZoneAndUri(zoneId, uri) > 0) {
- throw new InvalidParameterValueException("Network with vlan " + vlanId + " already exists in zone " + zoneId);
+ if (_networksDao.listByZoneAndUriAndGuestType(zoneId, uri.toString(), null).size() > 0) {
+ throw new InvalidParameterValueException("Network with vlan " + vlanId + " already exists or overlaps with other network vlans in zone " + zoneId);
} else {
- final List<DataCenterVnetVO> dcVnets = _datacenterVnetDao.findVnet(zoneId, vlanId.toString());
+ final List<DataCenterVnetVO> dcVnets = _datacenterVnetDao.findVnet(zoneId, BroadcastDomainType.getValue(uri));
//for the network that is created as part of private gateway,
//the vnet is not coming from the data center vnet table, so the list can be empty
if (!dcVnets.isEmpty()) {
@@ -2175,8 +2179,8 @@ public Network createGuestNetwork(final long networkOfferingId, final String nam
} else {
// don't allow to creating shared network with given Vlan ID, if there already exists a isolated network or
// shared network with same Vlan ID in the zone
- if (_networksDao.countByZoneUriAndGuestType(zoneId, uri, GuestType.Isolated) > 0 ) {
- throw new InvalidParameterValueException("There is a isolated/shared network with vlan id: " + vlanId + " already exists " + "in zone " + zoneId);
+ if (!bypassVlanOverlapCheck && _networksDao.listByZoneAndUriAndGuestType(zoneId, uri.toString(), GuestType.Isolated).size() > 0 ) {
+ throw new InvalidParameterValueException("There is an existing isolated/shared network that overlaps with vlan id:" + vlanId + " in zone " + zoneId);
}
}
}
@@ -3488,6 +3492,39 @@ public NicProfile createNicForVm(final Network network, final NicProfile request
return profiles;
}
+ @Override
+ public Map<String, String> getSystemVMAccessDetails(final VirtualMachine vm) {
+ final Map<String, String> accessDetails = new HashMap<>();
+ accessDetails.put(NetworkElementCommand.ROUTER_NAME, vm.getInstanceName());
+ String privateIpAddress = null;
+ for (final NicProfile profile : getNicProfiles(vm)) {
+ if (profile == null) {
+ continue;
+ }
+ final Network network = _networksDao.findById(profile.getNetworkId());
+ if (network == null) {
+ continue;
+ }
+ final String address = profile.getIPv4Address();
+ if (network.getTrafficType() == Networks.TrafficType.Control) {
+ accessDetails.put(NetworkElementCommand.ROUTER_IP, address);
+ }
+ if (network.getTrafficType() == Networks.TrafficType.Guest) {
+ accessDetails.put(NetworkElementCommand.ROUTER_GUEST_IP, address);
+ }
+ if (network.getTrafficType() == Networks.TrafficType.Management) {
+ privateIpAddress = address;
+ }
+ if (network.getTrafficType() != null && !Strings.isNullOrEmpty(address)) {
+ accessDetails.put(network.getTrafficType().name(), address);
+ }
+ }
+ if (privateIpAddress != null && Strings.isNullOrEmpty(accessDetails.get(NetworkElementCommand.ROUTER_IP))) {
+ accessDetails.put(NetworkElementCommand.ROUTER_IP, privateIpAddress);
+ }
+ return accessDetails;
+ }
+
protected boolean stateTransitTo(final NetworkVO network, final Network.Event e) throws NoTransitionException {
return _stateMachine.transitTo(network, e, null, _networksDao);
}
@@ -3628,6 +3665,8 @@ public String getConfigComponentName() {
@Override
public ConfigKey<?>[] getConfigKeys() {
- return new ConfigKey<?>[] {NetworkGcWait, NetworkGcInterval, NetworkLockTimeout, GuestDomainSuffix, NetworkThrottlingRate, MinVRVersion};
+ return new ConfigKey<?>[] {NetworkGcWait, NetworkGcInterval, NetworkLockTimeout,
+ GuestDomainSuffix, NetworkThrottlingRate, MinVRVersion,
+ PromiscuousMode, MacAddressChanges, ForgedTransmits};
}
}
diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java
index 018c62e47be..7669b3b98a9 100644
--- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java
+++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java
@@ -1369,6 +1369,20 @@ public void prepare(VirtualMachineProfile vm, DeployDestination dest) throws Sto
if (task.type == VolumeTaskType.NOP) {
pool = (StoragePool)dataStoreMgr.getDataStore(task.pool.getId(), DataStoreRole.Primary);
vol = task.volume;
+ // For a zone-wide managed storage, it is possible that the VM can be started in another
+ // cluster. In that case make sure that the volume in in the right access group cluster.
+ if (pool.isManaged()) {
+ long oldHostId = vm.getVirtualMachine().getLastHostId();
+ long hostId = vm.getVirtualMachine().getHostId();
+ if (oldHostId != hostId) {
+ Host oldHost = _hostDao.findById(oldHostId);
+ Host host = _hostDao.findById(hostId);
+ DataStore storagePool = dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary);
+
+ volService.revokeAccess(volFactory.getVolume(vol.getId()), oldHost, storagePool);
+ volService.grantAccess(volFactory.getVolume(vol.getId()), host, storagePool);
+ }
+ }
} else if (task.type == VolumeTaskType.MIGRATE) {
pool = (StoragePool)dataStoreMgr.getDataStore(task.pool.getId(), DataStoreRole.Primary);
vol = migrateVolume(task.volume, pool);
@@ -1395,21 +1409,16 @@ public void prepare(VirtualMachineProfile vm, DeployDestination dest) throws Sto
if (value != null && value) {
cloneType = UserVmCloneType.full;
}
- try {
- UserVmCloneSettingVO cloneSettingVO = _vmCloneSettingDao.findByVmId(vm.getId());
- if (cloneSettingVO != null){
- if (! cloneSettingVO.getCloneType().equals(cloneType.toString())){
- cloneSettingVO.setCloneType(cloneType.toString());
- _vmCloneSettingDao.update(cloneSettingVO.getVmId(), cloneSettingVO);
- }
- }
- else {
- UserVmCloneSettingVO vmCloneSettingVO = new UserVmCloneSettingVO(vm.getId(), cloneType.toString());
- _vmCloneSettingDao.persist(vmCloneSettingVO);
+ UserVmCloneSettingVO cloneSettingVO = _vmCloneSettingDao.findByVmId(vm.getId());
+ if (cloneSettingVO != null){
+ if (! cloneSettingVO.getCloneType().equals(cloneType.toString())){
+ cloneSettingVO.setCloneType(cloneType.toString());
+ _vmCloneSettingDao.update(cloneSettingVO.getVmId(), cloneSettingVO);
}
}
- catch (Throwable e){
- s_logger.debug("[NSX_PLUGIN_LOG] ERROR: " + e.getMessage());
+ else {
+ UserVmCloneSettingVO vmCloneSettingVO = new UserVmCloneSettingVO(vm.getId(), cloneType.toString());
+ _vmCloneSettingDao.persist(vmCloneSettingVO);
}
}
@@ -1444,9 +1453,13 @@ public boolean canVmRestartOnAnotherServer(long vmId) {
public static final ConfigKey<Boolean> StorageMigrationEnabled = new ConfigKey<Boolean>(Boolean.class, "enable.storage.migration", "Storage", "true",
"Enable/disable storage migration across primary storage", true);
+ static final ConfigKey<Boolean> VolumeUrlCheck = new ConfigKey<Boolean>("Advanced", Boolean.class, "volume.url.check", "true",
+ "Check the url for a volume before downloading it from the management server. Set to flase when you managment has no internet access.",
+ true);
+
@Override
public ConfigKey<?>[] getConfigKeys() {
- return new ConfigKey<?>[] {RecreatableSystemVmEnabled, MaxVolumeSize, StorageHAMigrationEnabled, StorageMigrationEnabled, CustomDiskOfferingMaxSize, CustomDiskOfferingMinSize};
+ return new ConfigKey<?>[] {RecreatableSystemVmEnabled, MaxVolumeSize, StorageHAMigrationEnabled, StorageMigrationEnabled, CustomDiskOfferingMaxSize, CustomDiskOfferingMinSize, VolumeUrlCheck};
}
@Override
diff --git a/engine/pom.xml b/engine/pom.xml
index d9b7fe5d779..1bf1249ffbd 100644
--- a/engine/pom.xml
+++ b/engine/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<build>
diff --git a/engine/schema/pom.xml b/engine/schema/pom.xml
index 848ed64549d..594225a520c 100644
--- a/engine/schema/pom.xml
+++ b/engine/schema/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml
index 117370720da..2075b933b64 100644
--- a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml
+++ b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml
@@ -130,6 +130,7 @@
<bean id="autoScaleVmProfileDaoImpl" class="com.cloud.network.as.dao.AutoScaleVmProfileDaoImpl" />
<bean id="capacityDaoImpl" class="com.cloud.capacity.dao.CapacityDaoImpl" />
<bean id="certificateDaoImpl" class="com.cloud.certificate.dao.CertificateDaoImpl" />
+ <bean id="crlDaoImpl" class="com.cloud.certificate.dao.CrlDaoImpl" />
<bean id="clusterDaoImpl" class="com.cloud.dc.dao.ClusterDaoImpl" />
<bean id="clusterDetailsDaoImpl" class="com.cloud.dc.ClusterDetailsDaoImpl" />
<bean id="clusterVSMMapDaoImpl" class="com.cloud.dc.dao.ClusterVSMMapDaoImpl" />
@@ -168,6 +169,8 @@
<bean id="guestOSCategoryDaoImpl" class="com.cloud.storage.dao.GuestOSCategoryDaoImpl" />
<bean id="guestOSDaoImpl" class="com.cloud.storage.dao.GuestOSDaoImpl" />
<bean id="guestOSHypervisorDaoImpl" class="com.cloud.storage.dao.GuestOSHypervisorDaoImpl" />
+ <!-- New HA Config -->
+ <bean id="haConfigDaoImpl" class="org.apache.cloudstack.ha.dao.HAConfigDaoImpl" />
<bean id="highAvailabilityDaoImpl" class="com.cloud.ha.dao.HighAvailabilityDaoImpl" />
<bean id="hostDaoImpl" class="com.cloud.host.dao.HostDaoImpl" />
<bean id="engineHostDetailsDaoImpl" class="org.apache.cloudstack.engine.datacenter.entity.api.db.dao.HostDetailsDaoImpl" />
@@ -270,7 +273,6 @@
<bean id="storagePoolTagsDaoImpl" class="com.cloud.storage.dao.StoragePoolTagsDaoImpl" />
<bean id="hostTagDaoImpl" class="com.cloud.api.query.dao.HostTagDaoImpl" />
<bean id="storagePoolWorkDaoImpl" class="com.cloud.storage.dao.StoragePoolWorkDaoImpl" />
- <bean id="templatePrimaryDataStoreDaoImpl" class="org.apache.cloudstack.storage.volume.db.TemplatePrimaryDataStoreDaoImpl" />
<bean id="uploadDaoImpl" class="com.cloud.storage.dao.UploadDaoImpl" />
<bean id="usageDaoImpl" class="com.cloud.usage.dao.UsageDaoImpl" />
<bean id="usageEventDaoImpl" class="com.cloud.event.dao.UsageEventDaoImpl" />
@@ -351,4 +353,5 @@
<bean id="LBHealthCheckPolicyDetailsDaoImpl" class="org.apache.cloudstack.resourcedetail.dao.LBHealthCheckPolicyDetailsDaoImpl" />
<bean id="outOfBandManagementDaoImpl" class="org.apache.cloudstack.outofbandmanagement.dao.OutOfBandManagementDaoImpl" />
<bean id="GuestOsDetailsDaoImpl" class="org.apache.cloudstack.resourcedetail.dao.GuestOsDetailsDaoImpl" />
+ <bean id="annotationDaoImpl" class="org.apache.cloudstack.annotation.dao.AnnotationDaoImpl" />
</beans>
diff --git a/engine/schema/src/com/cloud/capacity/CapacityVO.java b/engine/schema/src/com/cloud/capacity/CapacityVO.java
index 8df5c861cda..aaae874182f 100644
--- a/engine/schema/src/com/cloud/capacity/CapacityVO.java
+++ b/engine/schema/src/com/cloud/capacity/CapacityVO.java
@@ -17,6 +17,8 @@
package com.cloud.capacity;
import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
import javax.persistence.Column;
import javax.persistence.Entity;
@@ -75,6 +77,9 @@
@Transient
private Float usedPercentage;
+ @Transient
+ private Long allocatedCapacity;
+
public CapacityVO() {
}
@@ -208,8 +213,37 @@ public void setUsedPercentage(float usedPercentage) {
this.usedPercentage = usedPercentage;
}
+ public Long getAllocatedCapacity() {
+ return allocatedCapacity;
+ }
+
+ public void setAllocatedCapacity(Long allocatedCapacity) {
+ this.allocatedCapacity = allocatedCapacity;
+ }
+
@Override
public String getUuid() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
+
+ private static Map<Short, String> capacityNames = null;
+ static {
+ capacityNames = new HashMap<Short, String>();
+ capacityNames.put(CAPACITY_TYPE_MEMORY, "MEMORY");
+ capacityNames.put(CAPACITY_TYPE_CPU, "CPU");
+ capacityNames.put(CAPACITY_TYPE_STORAGE, "STORAGE");
+ capacityNames.put(CAPACITY_TYPE_STORAGE_ALLOCATED, "STORAGE_ALLOCATED");
+ capacityNames.put(CAPACITY_TYPE_VIRTUAL_NETWORK_PUBLIC_IP, "VIRTUAL_NETWORK_PUBLIC_IP");
+ capacityNames.put(CAPACITY_TYPE_PRIVATE_IP, "PRIVATE_IP");
+ capacityNames.put(CAPACITY_TYPE_SECONDARY_STORAGE, "SECONDARY_STORAGE");
+ capacityNames.put(CAPACITY_TYPE_VLAN, "VLAN");
+ capacityNames.put(CAPACITY_TYPE_DIRECT_ATTACHED_PUBLIC_IP, "DIRECT_ATTACHED_PUBLIC_IP");
+ capacityNames.put(CAPACITY_TYPE_LOCAL_STORAGE, "LOCAL_STORAGE");
+ capacityNames.put(CAPACITY_TYPE_GPU, "GPU");
+ capacityNames.put(CAPACITY_TYPE_CPU_CORE, "CPU_CORE");
+ }
+
+ public static String getCapacityName (Short capacityType) {
+ return capacityNames.get(capacityType);
+ }
}
diff --git a/engine/schema/src/com/cloud/capacity/dao/CapacityDaoImpl.java b/engine/schema/src/com/cloud/capacity/dao/CapacityDaoImpl.java
index f4e78051046..5b14bd4af3b 100644
--- a/engine/schema/src/com/cloud/capacity/dao/CapacityDaoImpl.java
+++ b/engine/schema/src/com/cloud/capacity/dao/CapacityDaoImpl.java
@@ -187,6 +187,17 @@
+
"from op_host_capacity capacity where cluster_id = ? and capacity_type = ?;";
+ private static final String LIST_ALLOCATED_CAPACITY_GROUP_BY_CAPACITY_AND_ZONE = "SELECT v.data_center_id, SUM(cpu) AS cpucore, " +
+ "SUM(cpu * speed) AS cpu, SUM(ram_size * 1024 * 1024) AS memory " +
+ "FROM (SELECT vi.data_center_id, (CASE WHEN ISNULL(service_offering.cpu) THEN custom_cpu.value ELSE service_offering.cpu end) AS cpu, " +
+ "(CASE WHEN ISNULL(service_offering.speed) THEN custom_speed.value ELSE service_offering.speed end) AS speed, " +
+ "(CASE WHEN ISNULL(service_offering.ram_size) THEN custom_ram_size.value ELSE service_offering.ram_size end) AS ram_size " +
+ "FROM (((vm_instance vi LEFT JOIN service_offering ON(((vi.service_offering_id = service_offering.id))) " +
+ "LEFT JOIN user_vm_details custom_cpu ON(((custom_cpu.vm_id = vi.id) AND (custom_cpu.name = 'CpuNumber')))) " +
+ "LEFT JOIN user_vm_details custom_speed ON(((custom_speed.vm_id = vi.id) AND (custom_speed.name = 'CpuSpeed')))) " +
+ "LEFT JOIN user_vm_details custom_ram_size ON(((custom_ram_size.vm_id = vi.id) AND (custom_ram_size.name = 'memory')))) " +
+ "WHERE ISNULL(vi.removed) AND vi.state NOT IN ('Destroyed', 'Error', 'Expunging')";
+
public CapacityDaoImpl() {
_hostIdTypeSearch = createSearchBuilder();
_hostIdTypeSearch.and("hostId", _hostIdTypeSearch.entity().getHostOrPoolId(), SearchCriteria.Op.EQ);
@@ -407,6 +418,33 @@ public static void setValues(PreparedStatement preparedStatement, Object... valu
PreparedStatement pstmt = null;
List<SummedCapacity> results = new ArrayList<SummedCapacity>();
+ StringBuilder allocatedSql = new StringBuilder(LIST_ALLOCATED_CAPACITY_GROUP_BY_CAPACITY_AND_ZONE);
+
+ HashMap<Long, Long> sumCpuCore = new HashMap<Long, Long>();
+ HashMap<Long, Long> sumCpu = new HashMap<Long, Long>();
+ HashMap<Long, Long> sumMemory = new HashMap<Long, Long>();
+ if (zoneId != null){
+ allocatedSql.append(" AND vi.data_center_id = ?");
+ }
+ allocatedSql.append(" ) AS v GROUP BY v.data_center_id");
+ try {
+ if (podId == null && clusterId == null) {
+ // add allocated capacity of zone in result
+ pstmt = txn.prepareAutoCloseStatement(allocatedSql.toString());
+ if (zoneId != null){
+ pstmt.setLong(1, zoneId);
+ }
+ ResultSet rs = pstmt.executeQuery();
+ if (rs.next()) {
+ sumCpuCore.put(rs.getLong(1), rs.getLong(2));
+ sumCpu.put(rs.getLong(1), rs.getLong(3));
+ sumMemory.put(rs.getLong(1), rs.getLong(4));
+ }
+ }
+ } catch (SQLException e) {
+ throw new CloudRuntimeException("DB Exception on: " + allocatedSql, e);
+ }
+
StringBuilder sql = new StringBuilder(LIST_CAPACITY_GROUP_BY_CAPACITY_PART1);
List<Long> resourceIdList = new ArrayList<Long>();
@@ -427,7 +465,11 @@ public static void setValues(PreparedStatement preparedStatement, Object... valu
resourceIdList.add(capacityType.longValue());
}
- sql.append(LIST_CAPACITY_GROUP_BY_CAPACITY_DATA_CENTER_POD_CLUSTER);
+ if (podId == null && clusterId == null) {
+ sql.append(" GROUP BY capacity_type, data_center_id");
+ } else {
+ sql.append(LIST_CAPACITY_GROUP_BY_CAPACITY_DATA_CENTER_POD_CLUSTER);
+ }
try {
pstmt = txn.prepareAutoCloseStatement(sql.toString());
@@ -438,6 +480,7 @@ public static void setValues(PreparedStatement preparedStatement, Object... valu
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
+ Long capacityZoneId = rs.getLong(6);
Long capacityPodId = null;
Long capacityClusterId = null;
@@ -450,6 +493,16 @@ public static void setValues(PreparedStatement preparedStatement, Object... valu
(short)rs.getLong(5), rs.getLong(6),
capacityPodId, capacityClusterId);
+ if (podId == null && clusterId == null) {
+ Short sumCapacityType = summedCapacity.getCapacityType();
+ if (sumCapacityType == CapacityVO.CAPACITY_TYPE_MEMORY) {
+ summedCapacity.setAllocatedCapacity(sumMemory.get(capacityZoneId));
+ } else if (sumCapacityType == CapacityVO.CAPACITY_TYPE_CPU) {
+ summedCapacity.setAllocatedCapacity(sumCpu.get(capacityZoneId));
+ } else if (sumCapacityType == CapacityVO.CAPACITY_TYPE_CPU_CORE) {
+ summedCapacity.setAllocatedCapacity(sumCpuCore.get(capacityZoneId));
+ }
+ }
results.add(summedCapacity);
}
HashMap<String, SummedCapacity> capacityMap = new HashMap<String, SummedCapacity>();
@@ -460,7 +513,7 @@ public static void setValues(PreparedStatement preparedStatement, Object... valu
}
else {
// sum the values based on the zoneId.
- key=String.valueOf(result.getDataCenterId())+String.valueOf(result.getCapacityType());
+ key=String.valueOf(result.getDataCenterId()) + "-" + String.valueOf(result.getCapacityType());
}
SummedCapacity tempCapacity=null;
if (capacityMap.containsKey(key)) {
@@ -589,6 +642,7 @@ public CapacityVO findByHostIdType(Long hostId, short capacityType) {
}
public static class SummedCapacity {
+ public Long sumAllocated;
public long sumUsed;
public long sumReserved;
public long sumTotal;
@@ -679,6 +733,12 @@ public void setPodId(Long podId) {
public void setClusterId(Long clusterId) {
this.clusterId=clusterId;
}
+ public Long getAllocatedCapacity() {
+ return sumAllocated;
+ }
+ public void setAllocatedCapacity(Long sumAllocated) {
+ this.sumAllocated = sumAllocated;
+ }
}
@Override
diff --git a/engine/schema/src/com/cloud/certificate/CrlVO.java b/engine/schema/src/com/cloud/certificate/CrlVO.java
new file mode 100644
index 00000000000..6df7530b290
--- /dev/null
+++ b/engine/schema/src/com/cloud/certificate/CrlVO.java
@@ -0,0 +1,85 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package com.cloud.certificate;
+
+import java.math.BigInteger;
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import org.apache.cloudstack.api.InternalIdentity;
+
+@Entity
+@Table(name = "crl")
+public class CrlVO implements InternalIdentity {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private Long id = null;
+
+ @Column(name = "serial")
+ private String certSerial;
+
+ @Column(name = "cn")
+ private String certCn;
+
+ @Column(name = "revoker_uuid")
+ private String revokerUuid;
+
+ @Temporal(value = TemporalType.TIMESTAMP)
+ @Column(name = "revoked", updatable = true)
+ private Date revoked;
+
+ public CrlVO() {
+ }
+
+ public CrlVO(final BigInteger certSerial, final String certCn, final String revokerUuid) {
+ this.certSerial = certSerial.toString(16);
+ this.certCn = certCn;
+ this.revokerUuid = revokerUuid;
+ this.revoked = new Date();
+ }
+
+ @Override
+ public long getId() {
+ return id;
+ }
+
+ public BigInteger getCertSerial() {
+ return new BigInteger(certSerial, 16);
+ }
+
+ public String getCertCn() {
+ return certCn;
+ }
+
+ public String getRevokerUuid() {
+ return revokerUuid;
+ }
+
+ public Date getRevoked() {
+ return revoked;
+ }
+}
diff --git a/engine/schema/src/com/cloud/certificate/dao/CrlDao.java b/engine/schema/src/com/cloud/certificate/dao/CrlDao.java
new file mode 100644
index 00000000000..613d9caf487
--- /dev/null
+++ b/engine/schema/src/com/cloud/certificate/dao/CrlDao.java
@@ -0,0 +1,28 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package com.cloud.certificate.dao;
+
+import java.math.BigInteger;
+
+import com.cloud.certificate.CrlVO;
+import com.cloud.utils.db.GenericDao;
+
+public interface CrlDao extends GenericDao<CrlVO, Long> {
+ CrlVO findBySerial(final BigInteger certSerial);
+ CrlVO revokeCertificate(final BigInteger certSerial, final String certCn);
+}
\ No newline at end of file
diff --git a/engine/schema/src/com/cloud/certificate/dao/CrlDaoImpl.java b/engine/schema/src/com/cloud/certificate/dao/CrlDaoImpl.java
new file mode 100644
index 00000000000..2eee308f115
--- /dev/null
+++ b/engine/schema/src/com/cloud/certificate/dao/CrlDaoImpl.java
@@ -0,0 +1,57 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package com.cloud.certificate.dao;
+
+import java.math.BigInteger;
+
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.certificate.CrlVO;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+
+@DB
+public class CrlDaoImpl extends GenericDaoBase<CrlVO, Long> implements CrlDao {
+
+ private final SearchBuilder<CrlVO> CrlBySerialSearch;
+
+ public CrlDaoImpl() {
+ super();
+
+ CrlBySerialSearch = createSearchBuilder();
+ CrlBySerialSearch.and("certSerial", CrlBySerialSearch.entity().getCertSerial(), SearchCriteria.Op.EQ);
+ CrlBySerialSearch.done();
+ }
+
+ @Override
+ public CrlVO findBySerial(final BigInteger certSerial) {
+ if (certSerial == null) {
+ return null;
+ }
+ final SearchCriteria<CrlVO> sc = CrlBySerialSearch.create("certSerial", certSerial.toString(16));
+ return findOneBy(sc);
+ }
+
+ @Override
+ public CrlVO revokeCertificate(final BigInteger certSerial, final String certCn) {
+ final CrlVO revokedCertificate = new CrlVO(certSerial, certCn == null ? "" : certCn, CallContext.current().getCallingUserUuid());
+ return persist(revokedCertificate);
+ }
+}
diff --git a/engine/schema/src/com/cloud/dc/ClusterVO.java b/engine/schema/src/com/cloud/dc/ClusterVO.java
index b701542fbdb..2a76789136a 100644
--- a/engine/schema/src/com/cloud/dc/ClusterVO.java
+++ b/engine/schema/src/com/cloud/dc/ClusterVO.java
@@ -16,8 +16,12 @@
// under the License.
package com.cloud.dc;
-import java.util.Date;
-import java.util.UUID;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.org.Cluster;
+import com.cloud.org.Grouping;
+import com.cloud.org.Managed.ManagedState;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.db.GenericDao;
import javax.persistence.Column;
import javax.persistence.Entity;
@@ -27,13 +31,8 @@
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
-
-import com.cloud.hypervisor.Hypervisor.HypervisorType;
-import com.cloud.org.Cluster;
-import com.cloud.org.Grouping;
-import com.cloud.org.Managed.ManagedState;
-import com.cloud.utils.NumbersUtil;
-import com.cloud.utils.db.GenericDao;
+import java.util.Date;
+import java.util.UUID;
@Entity
@Table(name = "cluster")
@@ -192,4 +191,9 @@ public String getUuid() {
public void setUuid(String uuid) {
this.uuid = uuid;
}
+
+ @Override
+ public PartitionType partitionType() {
+ return PartitionType.Cluster;
+ }
}
diff --git a/engine/schema/src/com/cloud/dc/DataCenterVO.java b/engine/schema/src/com/cloud/dc/DataCenterVO.java
index 42ea34a4704..4ab0eada1e1 100644
--- a/engine/schema/src/com/cloud/dc/DataCenterVO.java
+++ b/engine/schema/src/com/cloud/dc/DataCenterVO.java
@@ -16,9 +16,10 @@
// under the License.
package com.cloud.dc;
-import java.util.Date;
-import java.util.Map;
-import java.util.UUID;
+import com.cloud.network.Network.Provider;
+import com.cloud.org.Grouping;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.db.GenericDao;
import javax.persistence.Column;
import javax.persistence.Entity;
@@ -30,11 +31,9 @@
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.Transient;
-
-import com.cloud.network.Network.Provider;
-import com.cloud.org.Grouping;
-import com.cloud.utils.NumbersUtil;
-import com.cloud.utils.db.GenericDao;
+import java.util.Date;
+import java.util.Map;
+import java.util.UUID;
@Entity
@Table(name = "data_center")
@@ -454,4 +453,9 @@ public String getIp6Dns2() {
public void setIp6Dns2(String ip6Dns2) {
this.ip6Dns2 = ip6Dns2;
}
+
+ @Override
+ public PartitionType partitionType() {
+ return PartitionType.Zone;
+ }
}
diff --git a/engine/schema/src/com/cloud/dc/dao/DataCenterIpAddressDao.java b/engine/schema/src/com/cloud/dc/dao/DataCenterIpAddressDao.java
index e5843b69499..3b988dac21f 100644
--- a/engine/schema/src/com/cloud/dc/dao/DataCenterIpAddressDao.java
+++ b/engine/schema/src/com/cloud/dc/dao/DataCenterIpAddressDao.java
@@ -47,4 +47,6 @@
boolean deleteIpAddressByPod(long podId);
+ void releasePodIpAddress(long id);
+
}
diff --git a/engine/schema/src/com/cloud/dc/dao/DataCenterIpAddressDaoImpl.java b/engine/schema/src/com/cloud/dc/dao/DataCenterIpAddressDaoImpl.java
index ae8ae0cbb54..e840a4d91b0 100644
--- a/engine/schema/src/com/cloud/dc/dao/DataCenterIpAddressDaoImpl.java
+++ b/engine/schema/src/com/cloud/dc/dao/DataCenterIpAddressDaoImpl.java
@@ -176,6 +176,19 @@ public void releaseIpAddress(long nicId, String reservationId) {
update(vo, sc);
}
+ @Override
+ public void releasePodIpAddress(long id) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Releasing ip address for ID=" + id);
+ }
+
+ DataCenterIpAddressVO vo = this.findById(id);
+ vo.setTakenAt(null);
+ vo.setInstanceId(null);
+ vo.setReservationId(null);
+ persist(vo);
+ }
+
@Override
public void releaseIpAddress(long nicId) {
if (s_logger.isDebugEnabled()) {
diff --git a/engine/schema/src/com/cloud/dc/dao/DataCenterVnetDao.java b/engine/schema/src/com/cloud/dc/dao/DataCenterVnetDao.java
index 1783231f4fb..556ab451391 100644
--- a/engine/schema/src/com/cloud/dc/dao/DataCenterVnetDao.java
+++ b/engine/schema/src/com/cloud/dc/dao/DataCenterVnetDao.java
@@ -27,10 +27,10 @@
public List<DataCenterVnetVO> listAllocatedVnetsInRange(long dcId, long physicalNetworkId, Integer start, Integer end);
- public List<DataCenterVnetVO> findVnet(long dcId, String vnet);
-
public int countZoneVlans(long dcId, boolean onlyCountAllocated);
+ public List<DataCenterVnetVO> findVnet(long dcId, String vnet);
+
public List<DataCenterVnetVO> findVnet(long dcId, long physicalNetworkId, String vnet);
public void add(long dcId, long physicalNetworkId, List<String> vnets);
diff --git a/engine/schema/src/com/cloud/dc/dao/DataCenterVnetDaoImpl.java b/engine/schema/src/com/cloud/dc/dao/DataCenterVnetDaoImpl.java
index 3205fcd6af6..1c29e6a944c 100644
--- a/engine/schema/src/com/cloud/dc/dao/DataCenterVnetDaoImpl.java
+++ b/engine/schema/src/com/cloud/dc/dao/DataCenterVnetDaoImpl.java
@@ -18,6 +18,7 @@
import java.sql.PreparedStatement;
import java.sql.SQLException;
+import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
@@ -30,6 +31,8 @@
import com.cloud.dc.DataCenterVnetVO;
import com.cloud.network.dao.AccountGuestVlanMapDao;
import com.cloud.network.dao.AccountGuestVlanMapVO;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.UriUtils;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
@@ -99,15 +102,6 @@ public void lockRange(long dcId, long physicalNetworkId, Integer start, Integer
lockRows(sc, null, true);
}
- @Override
- public List<DataCenterVnetVO> findVnet(long dcId, String vnet) {
- SearchCriteria<DataCenterVnetVO> sc = VnetDcSearch.create();
- ;
- sc.setParameters("dc", dcId);
- sc.setParameters("vnet", vnet);
- return listBy(sc);
- }
-
@Override
public int countZoneVlans(long dcId, boolean onlyCountAllocated) {
SearchCriteria<Integer> sc = onlyCountAllocated ? countAllocatedZoneVlans.create() : countZoneVlans.create();
@@ -115,14 +109,37 @@ public int countZoneVlans(long dcId, boolean onlyCountAllocated) {
return customSearch(sc, null).get(0);
}
- @Override
- public List<DataCenterVnetVO> findVnet(long dcId, long physicalNetworkId, String vnet) {
+ private List<DataCenterVnetVO> findOverlappingVnets(final long dcId, final Long physicalNetworkId, final String vnet) {
+ final List<Integer> searchVnets = UriUtils.expandVlanUri(vnet);
+ final List<DataCenterVnetVO> overlappingVnets = new ArrayList<>();
+ if (searchVnets == null || searchVnets.isEmpty()) {
+ return overlappingVnets;
+ }
SearchCriteria<DataCenterVnetVO> sc = VnetDcSearch.create();
sc.setParameters("dc", dcId);
- sc.setParameters("physicalNetworkId", physicalNetworkId);
- sc.setParameters("vnet", vnet);
+ if (physicalNetworkId != null) {
+ sc.setParameters("physicalNetworkId", physicalNetworkId);
+ }
+ for (final DataCenterVnetVO dcVNet : listBy(sc)) {
+ if (dcVNet == null || dcVNet.getVnet() == null) {
+ continue;
+ }
+ final Integer vnetValue = NumbersUtil.parseInt(dcVNet.getVnet(), -1);
+ if (vnetValue != -1 && searchVnets.contains(vnetValue)) {
+ overlappingVnets.add(dcVNet);
+ }
+ }
+ return overlappingVnets;
+ }
- return listBy(sc);
+ @Override
+ public List<DataCenterVnetVO> findVnet(long dcId, String vnet) {
+ return findOverlappingVnets(dcId, null, vnet);
+ }
+
+ @Override
+ public List<DataCenterVnetVO> findVnet(long dcId, long physicalNetworkId, String vnet) {
+ return findOverlappingVnets(dcId, physicalNetworkId, vnet);
}
@Override
diff --git a/engine/schema/src/com/cloud/dc/dao/HostPodDao.java b/engine/schema/src/com/cloud/dc/dao/HostPodDao.java
index 1a000d8830c..b2e9b898606 100644
--- a/engine/schema/src/com/cloud/dc/dao/HostPodDao.java
+++ b/engine/schema/src/com/cloud/dc/dao/HostPodDao.java
@@ -32,4 +32,6 @@
public List<Long> listDisabledPods(long zoneId);
public List<Long> listAllPods(Long zoneId);
+
+ public List<HostPodVO> listAllPodsByCidr(long zoneId, String cidr);
}
diff --git a/engine/schema/src/com/cloud/dc/dao/HostPodDaoImpl.java b/engine/schema/src/com/cloud/dc/dao/HostPodDaoImpl.java
index 1c83b3a4a78..3fbeb58c56f 100644
--- a/engine/schema/src/com/cloud/dc/dao/HostPodDaoImpl.java
+++ b/engine/schema/src/com/cloud/dc/dao/HostPodDaoImpl.java
@@ -137,4 +137,12 @@ public boolean remove(Long id) {
}
return customSearch(sc, null);
}
+ @Override
+ public List<HostPodVO> listAllPodsByCidr(long zoneId, String cidr) {
+ SearchCriteria<HostPodVO> sc = DataCenterAndNameSearch.create();
+ sc.setParameters("dataCenterId", zoneId);
+ sc.setParameters("cidr_address", cidr);
+ return listBy(sc);
+ }
+
}
diff --git a/engine/schema/src/com/cloud/host/HostVO.java b/engine/schema/src/com/cloud/host/HostVO.java
index c5938d65220..7fd1e710185 100644
--- a/engine/schema/src/com/cloud/host/HostVO.java
+++ b/engine/schema/src/com/cloud/host/HostVO.java
@@ -16,11 +16,12 @@
// under the License.
package com.cloud.host;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
+import com.cloud.agent.api.VgpuTypesInfo;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.resource.ResourceState;
+import com.cloud.storage.Storage.StoragePoolType;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.db.GenericDao;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
@@ -37,13 +38,11 @@
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
-
-import com.cloud.agent.api.VgpuTypesInfo;
-import com.cloud.hypervisor.Hypervisor.HypervisorType;
-import com.cloud.resource.ResourceState;
-import com.cloud.storage.Storage.StoragePoolType;
-import com.cloud.utils.NumbersUtil;
-import com.cloud.utils.db.GenericDao;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
@Entity
@Table(name = "host")
@@ -178,6 +177,11 @@ public Long getClusterId() {
return clusterId;
}
+ @Override
+ public ResourceType resourceType() {
+ return ResourceType.Host;
+ }
+
public void setClusterId(Long clusterId) {
this.clusterId = clusterId;
}
@@ -713,6 +717,11 @@ public boolean isInMaintenanceStates() {
return (getResourceState() == ResourceState.Maintenance || getResourceState() == ResourceState.ErrorInMaintenance || getResourceState() == ResourceState.PrepareForMaintenance);
}
+ @Override
+ public boolean isDisabled() {
+ return (getResourceState() == ResourceState.Disabled);
+ }
+
public long getUpdated() {
return updated;
}
@@ -730,4 +739,9 @@ public String getUuid() {
public void setUuid(String uuid) {
this.uuid = uuid;
}
+
+ @Override
+ public PartitionType partitionType() {
+ return PartitionType.Host;
+ }
}
diff --git a/engine/schema/src/com/cloud/host/dao/HostDao.java b/engine/schema/src/com/cloud/host/dao/HostDao.java
index 7ffe1ed2ed5..f98e8c19eeb 100644
--- a/engine/schema/src/com/cloud/host/dao/HostDao.java
+++ b/engine/schema/src/com/cloud/host/dao/HostDao.java
@@ -101,4 +101,6 @@
List<Long> listClustersByHostTag(String hostTagOnOffering);
List<HostVO> listByType(Type type);
+
+ HostVO findByIp(String ip);
}
diff --git a/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java b/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java
index a74b908457f..d08b40281e6 100644
--- a/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java
+++ b/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java
@@ -31,6 +31,8 @@
import javax.inject.Inject;
import javax.persistence.TableGenerator;
+import com.cloud.utils.NumbersUtil;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@@ -89,6 +91,7 @@
protected SearchBuilder<HostVO> DcPrivateIpAddressSearch;
protected SearchBuilder<HostVO> DcStorageIpAddressSearch;
protected SearchBuilder<HostVO> PublicIpAddressSearch;
+ protected SearchBuilder<HostVO> AnyIpAddressSearch;
protected SearchBuilder<HostVO> GuidSearch;
protected SearchBuilder<HostVO> DcSearch;
@@ -143,6 +146,8 @@
protected HostTransferMapDao _hostTransferDao;
@Inject
protected ClusterDao _clusterDao;
+ @Inject
+ private ConfigurationDao _configDao;
public HostDaoImpl() {
super();
@@ -216,6 +221,11 @@ public void init() {
PublicIpAddressSearch.and("publicIpAddress", PublicIpAddressSearch.entity().getPublicIpAddress(), SearchCriteria.Op.EQ);
PublicIpAddressSearch.done();
+ AnyIpAddressSearch = createSearchBuilder();
+ AnyIpAddressSearch.or("publicIpAddress", AnyIpAddressSearch.entity().getPublicIpAddress(), SearchCriteria.Op.EQ);
+ AnyIpAddressSearch.or("privateIpAddress", AnyIpAddressSearch.entity().getPrivateIpAddress(), SearchCriteria.Op.EQ);
+ AnyIpAddressSearch.done();
+
GuidSearch = createSearchBuilder();
GuidSearch.and("guid", GuidSearch.entity().getGuid(), SearchCriteria.Op.EQ);
GuidSearch.done();
@@ -377,6 +387,11 @@ public void init() {
ClustersForHostsNotOwnedByAnyMSSearch.and("resource", ClustersForHostsNotOwnedByAnyMSSearch.entity().getResource(), SearchCriteria.Op.NNULL);
ClustersForHostsNotOwnedByAnyMSSearch.and("cluster", ClustersForHostsNotOwnedByAnyMSSearch.entity().getClusterId(), SearchCriteria.Op.NNULL);
ClustersForHostsNotOwnedByAnyMSSearch.and("server", ClustersForHostsNotOwnedByAnyMSSearch.entity().getManagementServerId(), SearchCriteria.Op.NULL);
+
+ ClusterManagedSearch = _clusterDao.createSearchBuilder();
+ ClusterManagedSearch.and("managed", ClusterManagedSearch.entity().getManagedState(), SearchCriteria.Op.EQ);
+ ClustersForHostsNotOwnedByAnyMSSearch.join("ClusterManagedSearch", ClusterManagedSearch, ClusterManagedSearch.entity().getId(), ClustersForHostsNotOwnedByAnyMSSearch.entity().getClusterId(), JoinType.INNER);
+
ClustersForHostsNotOwnedByAnyMSSearch.done();
AllClustersSearch = _clusterDao.createSearchBuilder(Long.class);
@@ -501,6 +516,7 @@ private void resetHosts(long managementServerId, long lastPingSecondsAfter) {
*/
private List<Long> findClustersForHostsNotOwnedByAnyManagementServer() {
SearchCriteria<Long> sc = ClustersForHostsNotOwnedByAnyMSSearch.create();
+ sc.setJoinParameters("ClusterManagedSearch", "managed", Managed.ManagedState.Managed);
List<Long> clusters = customSearch(sc, null);
return clusters;
@@ -642,7 +658,7 @@ private boolean canOwnCluster(long clusterId) {
SearchCriteria<HostVO> sc = UnmanagedApplianceSearch.create();
sc.setParameters("lastPinged", lastPingSecondsAfter);
sc.setParameters("types", Type.ExternalDhcp, Type.ExternalFirewall, Type.ExternalLoadBalancer, Type.BaremetalDhcp, Type.BaremetalPxe, Type.TrafficMonitor,
- Type.L2Networking);
+ Type.L2Networking, Type.NetScalerControlCenter);
List<HostVO> hosts = lockRows(sc, null, true);
for (HostVO host : hosts) {
@@ -979,7 +995,9 @@ public boolean updateState(Status oldStatus, Event event, Status newStatus, Host
}
}
if (event.equals(Event.ManagementServerDown)) {
- ub.set(host, _pingTimeAttr, ((System.currentTimeMillis() >> 10) - (10 * 60)));
+ Float pingTimeout = NumbersUtil.parseFloat(_configDao.getValue("ping.timeout"), 2.5f);
+ Integer pingInterval = NumbersUtil.parseInt(_configDao.getValue("ping.interval"), 60);
+ ub.set(host, _pingTimeAttr, ((System.currentTimeMillis() >> 10) - (long)(pingTimeout * pingInterval)));
}
int result = update(ub, sc, null);
assert result <= 1 : "How can this update " + result + " rows? ";
@@ -1112,6 +1130,13 @@ public HostVO findByPublicIp(String publicIp) {
return findOneBy(sc);
}
+ @Override
+ public HostVO findByIp(final String ipAddress) {
+ SearchCriteria<HostVO> sc = AnyIpAddressSearch.create();
+ sc.setParameters("publicIpAddress", ipAddress);
+ sc.setParameters("privateIpAddress", ipAddress);
+ return findOneBy(sc);
+ }
@Override
public List<HostVO> findHypervisorHostInCluster(long clusterId) {
diff --git a/engine/schema/src/com/cloud/network/dao/NetworkDao.java b/engine/schema/src/com/cloud/network/dao/NetworkDao.java
index 684a94f3fff..5091ebd75df 100644
--- a/engine/schema/src/com/cloud/network/dao/NetworkDao.java
+++ b/engine/schema/src/com/cloud/network/dao/NetworkDao.java
@@ -61,9 +61,7 @@
List<NetworkVO> listBy(long accountId, long networkId);
- long countByZoneAndUri(long zoneId, String broadcastUri);
-
- long countByZoneUriAndGuestType(long zoneId, String broadcastUri, GuestType guestType);
+ List<NetworkVO> listByZoneAndUriAndGuestType(long zoneId, String broadcastUri, GuestType guestType);
List<NetworkVO> listByZone(long zoneId);
@@ -120,4 +118,6 @@
List<NetworkVO> listByAclId(long aclId);
int getNonSystemNetworkCountByVpcId(long vpcId);
+
+ List<NetworkVO> listNetworkVO(List<Long> idset);
}
diff --git a/engine/schema/src/com/cloud/network/dao/NetworkDaoImpl.java b/engine/schema/src/com/cloud/network/dao/NetworkDaoImpl.java
index 29d0e8f1718..11444b0d008 100644
--- a/engine/schema/src/com/cloud/network/dao/NetworkDaoImpl.java
+++ b/engine/schema/src/com/cloud/network/dao/NetworkDaoImpl.java
@@ -16,6 +16,8 @@
// under the License.
package com.cloud.network.dao;
+import java.net.URI;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
@@ -41,7 +43,9 @@
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.server.ResourceTag.ResourceObjectType;
import com.cloud.tags.dao.ResourceTagDao;
+import com.cloud.utils.UriUtils;
import com.cloud.utils.db.DB;
+import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.JoinBuilder;
@@ -56,7 +60,7 @@
@Component
@DB()
-public class NetworkDaoImpl extends GenericDaoBase<NetworkVO, Long> implements NetworkDao {
+public class NetworkDaoImpl extends GenericDaoBase<NetworkVO, Long>implements NetworkDao {
SearchBuilder<NetworkVO> AllFieldsSearch;
SearchBuilder<NetworkVO> AccountSearch;
SearchBuilder<NetworkVO> RelatedConfigSearch;
@@ -69,7 +73,6 @@
GenericSearchBuilder<NetworkVO, Long> NetworksRegularUserCanCreateSearch;
GenericSearchBuilder<NetworkVO, Integer> NetworksCount;
SearchBuilder<NetworkVO> SourceNATSearch;
- GenericSearchBuilder<NetworkVO, Long> CountByZoneAndURI;
GenericSearchBuilder<NetworkVO, Long> VpcNetworksCount;
SearchBuilder<NetworkVO> OfferingAccountNetworkSearch;
@@ -150,14 +153,6 @@ protected void init() {
ZoneBroadcastUriSearch.and("guestType", ZoneBroadcastUriSearch.entity().getGuestType(), Op.EQ);
ZoneBroadcastUriSearch.done();
- CountByZoneAndURI = createSearchBuilder(Long.class);
- CountByZoneAndURI.select(null, Func.COUNT, null);
- CountByZoneAndURI.and("dataCenterId", CountByZoneAndURI.entity().getDataCenterId(), Op.EQ);
- CountByZoneAndURI.and("broadcastUri", CountByZoneAndURI.entity().getBroadcastUri(), Op.EQ);
- CountByZoneAndURI.and("guestType", CountByZoneAndURI.entity().getGuestType(), Op.EQ);
-
- CountByZoneAndURI.done();
-
ZoneSecurityGroupSearch = createSearchBuilder();
ZoneSecurityGroupSearch.and("dataCenterId", ZoneSecurityGroupSearch.entity().getDataCenterId(), Op.EQ);
final SearchBuilder<NetworkServiceMapVO> offJoin = _ntwkSvcMap.createSearchBuilder();
@@ -275,7 +270,6 @@ protected void init() {
return listBy(sc, null);
}
-
public List<NetworkVO> findBy(final TrafficType trafficType, final Mode mode, final BroadcastDomainType broadcastType, final long networkOfferingId, final long dataCenterId) {
final SearchCriteria<NetworkVO> sc = AllFieldsSearch.create();
sc.setParameters("trafficType", trafficType);
@@ -398,13 +392,35 @@ public String getNextAvailableMacAddress(final long networkConfigId, Integer zon
}
@Override
- public long countByZoneAndUri(final long zoneId, final String broadcastUri) {
+ public List<NetworkVO> listByZoneAndUriAndGuestType(long zoneId, String broadcastUri, GuestType guestType) {
+ final URI searchUri = BroadcastDomainType.fromString(broadcastUri);
+ final String searchRange = BroadcastDomainType.getValue(searchUri);
+ final List<Integer> searchVlans = UriUtils.expandVlanUri(searchRange);
+ final List<NetworkVO> overlappingNetworks = new ArrayList<>();
- final SearchCriteria<Long> sc = CountByZoneAndURI.create();
+ final SearchCriteria<NetworkVO> sc = ZoneBroadcastUriSearch.create();
sc.setParameters("dataCenterId", zoneId);
- sc.setParameters("broadcastUri", broadcastUri);
+ if (guestType != null) {
+ sc.setParameters("guestType", guestType);
+ }
- return customSearch(sc, null).get(0);
+ for (final NetworkVO network : listBy(sc)) {
+ if (network.getBroadcastUri() == null || !network.getBroadcastUri().getScheme().equalsIgnoreCase(searchUri.getScheme())) {
+ continue;
+ }
+ final String networkVlanRange = BroadcastDomainType.getValue(network.getBroadcastUri());
+ if (networkVlanRange == null || networkVlanRange.isEmpty()) {
+ continue;
+ }
+ for (final Integer networkVlan : UriUtils.expandVlanUri(networkVlanRange)) {
+ if (searchVlans.contains(networkVlan)) {
+ overlappingNetworks.add(network);
+ break;
+ }
+ }
+ }
+
+ return overlappingNetworks;
}
@Override
@@ -414,15 +430,6 @@ public long countByZoneAndUri(final long zoneId, final String broadcastUri) {
return search(sc, null);
}
- @Override
- public long countByZoneUriAndGuestType(final long zoneId, final String broadcastUri, final GuestType guestType) {
- final SearchCriteria<Long> sc = CountByZoneAndURI.create();
- sc.setParameters("dataCenterId", zoneId);
- sc.setParameters("broadcastUri", broadcastUri);
- sc.setParameters("guestType", guestType);
- return customSearch(sc, null).get(0);
- }
-
@Override
public List<NetworkVO> listByZoneSecurityGroup(final Long zoneId) {
final SearchCriteria<NetworkVO> sc = ZoneSecurityGroupSearch.create();
@@ -680,4 +687,13 @@ public int getNonSystemNetworkCountByVpcId(final long vpcId) {
final List<Integer> results = customSearch(sc, null);
return results.get(0);
}
+
+ @Override
+ public List<NetworkVO> listNetworkVO(List<Long> idset) {
+ final SearchCriteria<NetworkVO> sc_2 = createSearchCriteria();
+ final Filter searchFilter_2 = new Filter(NetworkVO.class, "id", false, null, null);
+ sc_2.addAnd("networkOfferingId", SearchCriteria.Op.IN, idset);
+ sc_2.addAnd("removed", SearchCriteria.Op.EQ, null);
+ return this.search(sc_2, searchFilter_2);
+ }
}
diff --git a/engine/schema/src/com/cloud/network/dao/NetworkVO.java b/engine/schema/src/com/cloud/network/dao/NetworkVO.java
index ee5c6b54ef8..08a326a0e1e 100644
--- a/engine/schema/src/com/cloud/network/dao/NetworkVO.java
+++ b/engine/schema/src/com/cloud/network/dao/NetworkVO.java
@@ -67,7 +67,7 @@
String name;
@Column(name = "display_text")
- String displayText;;
+ String displayText;
@Column(name = "broadcast_uri")
URI broadcastUri;
@@ -299,14 +299,18 @@ public State getState() {
return state;
}
+ // don't use this directly when possible, use Network state machine instead
+ public void setState(State state) {
+ this.state = state;
+ }
+
@Override
public boolean isRedundant() {
return this.redundant;
}
- // don't use this directly when possible, use Network state machine instead
- public void setState(State state) {
- this.state = state;
+ public void setRedundant(boolean redundant) {
+ this.redundant = redundant;
}
@Override
@@ -630,9 +634,4 @@ public void setStrechedL2Network(boolean strechedL2Network) {
public void setVpcId(Long vpcId) {
this.vpcId = vpcId;
}
-
- public void setIsReduntant(boolean reduntant) {
- this.redundant = reduntant;
- }
-
}
diff --git a/engine/schema/src/com/cloud/network/dao/SslCertVO.java b/engine/schema/src/com/cloud/network/dao/SslCertVO.java
index 1d72180a107..2aaa6a2fd56 100644
--- a/engine/schema/src/com/cloud/network/dao/SslCertVO.java
+++ b/engine/schema/src/com/cloud/network/dao/SslCertVO.java
@@ -60,11 +60,14 @@
@Column(name = "fingerprint")
String fingerPrint;
+ @Column(name = "name")
+ String name;
+
public SslCertVO() {
uuid = UUID.randomUUID().toString();
}
- public SslCertVO(String cert, String key, String password, String chain, Long accountId, Long domainId, String fingerPrint) {
+ public SslCertVO(String cert, String key, String password, String chain, Long accountId, Long domainId, String fingerPrint, String name) {
certificate = cert;
this.key = key;
this.chain = chain;
@@ -73,6 +76,7 @@ public SslCertVO(String cert, String key, String password, String chain, Long ac
this.domainId = domainId;
this.fingerPrint = fingerPrint;
uuid = UUID.randomUUID().toString();
+ this.name = name;
}
// Getters
@@ -121,6 +125,11 @@ public String getFingerPrint() {
return fingerPrint;
}
+ @Override
+ public String getName() {
+ return name;
+ }
+
@Override
public Class<?> getEntityType() {
return SslCert.class;
diff --git a/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java b/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java
index 4325287b273..f40f71092e0 100644
--- a/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java
+++ b/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java
@@ -156,6 +156,9 @@ public String getDisplayText() {
@Column(name = "public_lb")
boolean publicLb;
+ @Column(name="service_package_id")
+ String servicePackageUuid = null;
+
@Override
public boolean isKeepAliveEnabled() {
return keepAliveEnabled;
@@ -500,8 +503,17 @@ public boolean getSupportsStrechedL2() {
return supportsStrechedL2;
}
+ public void setServicePackage(String servicePackageUuid) {
+ this.servicePackageUuid = servicePackageUuid;
+ }
+
@Override
public boolean getSupportsPublicAccess() {
return supportsPublicAccess;
}
+
+ @Override
+ public String getServicePackage() {
+ return servicePackageUuid;
+ }
}
diff --git a/engine/schema/src/com/cloud/offerings/dao/NetworkOfferingDao.java b/engine/schema/src/com/cloud/offerings/dao/NetworkOfferingDao.java
index b7aa94bbaa8..19beddd1001 100644
--- a/engine/schema/src/com/cloud/offerings/dao/NetworkOfferingDao.java
+++ b/engine/schema/src/com/cloud/offerings/dao/NetworkOfferingDao.java
@@ -61,4 +61,7 @@
NetworkOfferingVO persist(NetworkOfferingVO off, Map<Detail, String> details);
+ List<Long> listNetworkOfferingID();
+
+ boolean isUsingServicePackage(String uuid);
}
diff --git a/engine/schema/src/com/cloud/offerings/dao/NetworkOfferingDaoImpl.java b/engine/schema/src/com/cloud/offerings/dao/NetworkOfferingDaoImpl.java
index 5a6092ec243..b0cf0fe320b 100644
--- a/engine/schema/src/com/cloud/offerings/dao/NetworkOfferingDaoImpl.java
+++ b/engine/schema/src/com/cloud/offerings/dao/NetworkOfferingDaoImpl.java
@@ -16,12 +16,14 @@
// under the License.
package com.cloud.offerings.dao;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import javax.persistence.EntityExistsException;
+import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Component;
import com.cloud.network.Network;
@@ -32,6 +34,7 @@
import com.cloud.offerings.NetworkOfferingDetailsVO;
import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.utils.db.DB;
+import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.SearchBuilder;
@@ -189,4 +192,33 @@ public NetworkOfferingVO persist(NetworkOfferingVO off, Map<Detail, String> deta
return vo;
}
+ @Override
+ public List<Long> listNetworkOfferingID() {
+ final SearchCriteria<NetworkOfferingVO> sc_1 = createSearchCriteria();
+ final Filter searchFilter_1 = new Filter(NetworkOfferingVO.class, "created", false, null, null);
+ sc_1.addAnd("servicePackageUuid", SearchCriteria.Op.NEQ, null);
+ sc_1.addAnd("removed", SearchCriteria.Op.EQ, null);
+ List<NetworkOfferingVO> set_of_servicePackageUuid = this.search(sc_1, searchFilter_1);
+ List<Long> id_set = new ArrayList<Long>();
+ for (NetworkOfferingVO node : set_of_servicePackageUuid) {
+ if (node.getServicePackage() != null && !node.getServicePackage().isEmpty()) {
+ id_set.add(node.getId());
+ }
+ }
+ return id_set;
+ }
+
+ @Override
+ public boolean isUsingServicePackage(String uuid) {
+ final SearchCriteria<NetworkOfferingVO> sc = createSearchCriteria();
+ final Filter searchFilter= new Filter(NetworkOfferingVO.class, "created", false, null, null);
+ sc.addAnd("state", SearchCriteria.Op.EQ, NetworkOffering.State.Enabled);
+ sc.addAnd("servicePackageUuid", SearchCriteria.Op.EQ, uuid);
+ List<NetworkOfferingVO> list = this.search(sc, searchFilter);
+
+ if(CollectionUtils.isNotEmpty(list))
+ return true;
+
+ return false;
+ }
}
diff --git a/engine/schema/src/com/cloud/storage/SnapshotVO.java b/engine/schema/src/com/cloud/storage/SnapshotVO.java
index 8e5c0b6d6fa..f1041590fb7 100644
--- a/engine/schema/src/com/cloud/storage/SnapshotVO.java
+++ b/engine/schema/src/com/cloud/storage/SnapshotVO.java
@@ -162,6 +162,11 @@ public String getName() {
return name;
}
+ @Override
+ public long getSnapshotId() {
+ return id;
+ }
+
@Override
public short getsnapshotType() {
return snapshotType;
diff --git a/engine/schema/src/com/cloud/upgrade/DatabaseUpgradeChecker.java b/engine/schema/src/com/cloud/upgrade/DatabaseUpgradeChecker.java
index ccdf07700e4..fe211154065 100644
--- a/engine/schema/src/com/cloud/upgrade/DatabaseUpgradeChecker.java
+++ b/engine/schema/src/com/cloud/upgrade/DatabaseUpgradeChecker.java
@@ -67,6 +67,7 @@
import com.cloud.upgrade.dao.Upgrade4910to4920;
import com.cloud.upgrade.dao.Upgrade4920to4930;
import com.cloud.upgrade.dao.Upgrade4930to41000;
+import com.cloud.upgrade.dao.Upgrade41000to41100;
import com.cloud.upgrade.dao.UpgradeSnapshot217to224;
import com.cloud.upgrade.dao.UpgradeSnapshot223to224;
import com.cloud.upgrade.dao.VersionDao;
@@ -104,210 +105,347 @@
public class DatabaseUpgradeChecker implements SystemIntegrityChecker {
private static final Logger s_logger = Logger.getLogger(DatabaseUpgradeChecker.class);
-
+ private final ImmutableList<CloudStackVersion> availableVersions;
protected Map<CloudStackVersion, DbUpgrade[]> _upgradeMap = new HashMap<>();
@Inject
VersionDao _dao;
- private final ImmutableList<CloudStackVersion> availableVersions;
-
public DatabaseUpgradeChecker() {
_dao = new VersionDaoImpl();
- _upgradeMap.put(CloudStackVersion.parse("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(), new Upgrade2212to2213(), new Upgrade2213to2214(), new Upgrade2214to30(),
- new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(),
- new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(),
- new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("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(), new Upgrade2212to2213(), new Upgrade2213to2214(),
- new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(),
- new Upgrade410to420(), new Upgrade420to421(),
- new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("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(), new Upgrade2212to2213(), new Upgrade2213to2214(), new Upgrade2214to30(),
- new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(),
- new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(),
- new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("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(), new Upgrade2212to2213(),
- new Upgrade2213to2214(), new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(),
- new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(),
- new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("2.2.2"), new DbUpgrade[] {new Upgrade222to224(), new UpgradeSnapshot223to224(), new Upgrade224to225(),
- new Upgrade225to226(), new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(),
- new Upgrade2210to2211(), new Upgrade2211to2212(), new Upgrade2212to2213(), new Upgrade2213to2214(),
- new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(),
- new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("2.2.3"), new DbUpgrade[] {new Upgrade222to224(), new UpgradeSnapshot223to224(), new Upgrade224to225(),
- new Upgrade225to226(), new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(),
- new Upgrade2210to2211(), new Upgrade2211to2212(), new Upgrade2212to2213(), new Upgrade2213to2214(),
- new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(),
- new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("2.2.4"), new DbUpgrade[] {new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228(),
- new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212(),
- new Upgrade2212to2213(), new Upgrade2213to2214(), new Upgrade2214to30(), new Upgrade30to301(),
- new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(),
- new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("2.2.5"), new DbUpgrade[] {new Upgrade225to226(), new Upgrade227to228(), new Upgrade228to229(),
- new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212(), new Upgrade2212to2213(),
- new Upgrade2213to2214(), new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(),
- new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(),
- new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("2.2.6"), new DbUpgrade[] {new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(),
- new Upgrade2210to2211(), new Upgrade2211to2212(), new Upgrade2212to2213(), new Upgrade2213to2214(),
- new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(),
- new Upgrade410to420(), new Upgrade420to421(),
- new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("2.2.7"), new DbUpgrade[] {new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(),
- new Upgrade2210to2211(), new Upgrade2211to2212(), new Upgrade2212to2213(),
- new Upgrade2213to2214(), new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(),
- new Upgrade410to420(),
- new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(),
- new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("2.2.8"), new DbUpgrade[] {new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(),
- new Upgrade2211to2212(), new Upgrade2212to2213(), new Upgrade2213to2214(), new Upgrade2214to30()
- , new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(),
- new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("2.2.9"), new DbUpgrade[] {new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212(),
- new Upgrade2212to2213(), new Upgrade2213to2214(), new Upgrade2214to30(), new Upgrade30to301(),
- new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(),
- new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("2.2.10"), new DbUpgrade[] {new Upgrade2210to2211(), new Upgrade2211to2212(), new Upgrade2212to2213(),
- new Upgrade2213to2214(), new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(),
- new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(),
- new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("2.2.12"), new DbUpgrade[] {new Upgrade2212to2213(), new Upgrade2213to2214(), new Upgrade2214to30(),
- new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(),
- new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("2.2.13"), new DbUpgrade[] {new Upgrade2213to2214(), new Upgrade2214to30(), new Upgrade30to301(),
- new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(),
- new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("2.2.14"), new DbUpgrade[] {new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(),
- new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(),
- new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("3.0.0"), new DbUpgrade[] {new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(),
- new Upgrade40to41(), new Upgrade410to420(),
- new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("3.0.1"), new DbUpgrade[] {new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(),
- new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("3.0.2"), new DbUpgrade[] {new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(),
- new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.0.0"), new DbUpgrade[] {new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.0.1"), new DbUpgrade[] {new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.0.2"), new DbUpgrade[] {new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.1.0"), new DbUpgrade[] {new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.1.1"), new DbUpgrade[] {new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.2.0"), new DbUpgrade[] {new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.2.1"), new DbUpgrade[] {new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
+ _upgradeMap.put(CloudStackVersion.parse("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(),
+ new Upgrade2212to2213(), new Upgrade2213to2214(), new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(),
+ new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(),
+ new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(),
+ new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(),
+ new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("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(), new Upgrade2212to2213(), new Upgrade2213to2214(), new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(),
+ new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(),
+ new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(),
+ new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(),
+ new Upgrade4930to41000()});
+
+ _upgradeMap.put(CloudStackVersion.parse("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(), new Upgrade2212to2213(), new Upgrade2213to2214(), new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(),
+ new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(),
+ new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(),
+ new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(),
+ new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("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(), new Upgrade2212to2213(), new Upgrade2213to2214(),
+ new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(),
+ new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(),
+ new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(),
+ new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("2.2.2"),
+ new DbUpgrade[] {new Upgrade222to224(), new UpgradeSnapshot223to224(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228(), new Upgrade228to229(),
+ new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212(), new Upgrade2212to2213(), new Upgrade2213to2214(), new Upgrade2214to30(),
+ new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(),
+ new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(),
+ new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(),
+ new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("2.2.3"),
+ new DbUpgrade[] {new Upgrade222to224(), new UpgradeSnapshot223to224(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228(), new Upgrade228to229(),
+ new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212(), new Upgrade2212to2213(), new Upgrade2213to2214(), new Upgrade2214to30(),
+ new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(),
+ new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(),
+ new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(),
+ new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("2.2.4"),
+ new DbUpgrade[] {new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(),
+ new Upgrade2211to2212(), new Upgrade2212to2213(), new Upgrade2213to2214(), new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(),
+ new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(),
+ new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(),
+ new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(),
+ new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("2.2.5"),
+ new DbUpgrade[] {new Upgrade225to226(), new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212(),
+ new Upgrade2212to2213(), new Upgrade2213to2214(), new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(),
+ new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(),
+ new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(),
+ new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(),
+ new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("2.2.6"),
+ new DbUpgrade[] {new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212(), new Upgrade2212to2213(),
+ new Upgrade2213to2214(), new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(),
+ new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(),
+ new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(),
+ new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("2.2.7"),
+ new DbUpgrade[] {new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212(), new Upgrade2212to2213(),
+ new Upgrade2213to2214(), new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(),
+ new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(),
+ new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(),
+ new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("2.2.8"),
+ new DbUpgrade[] {new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212(), new Upgrade2212to2213(), new Upgrade2213to2214(),
+ new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(),
+ new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(),
+ new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(),
+ new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("2.2.9"),
+ new DbUpgrade[] {new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212(), new Upgrade2212to2213(), new Upgrade2213to2214(), new Upgrade2214to30(),
+ new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(),
+ new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(),
+ new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(),
+ new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("2.2.10"),
+ new DbUpgrade[] {new Upgrade2210to2211(), new Upgrade2211to2212(), new Upgrade2212to2213(), new Upgrade2213to2214(), new Upgrade2214to30(), new Upgrade30to301(),
+ new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(),
+ new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(),
+ new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(),
+ new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("2.2.12"),
+ new DbUpgrade[] {new Upgrade2212to2213(), new Upgrade2213to2214(), new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(),
+ new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(),
+ new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(),
+ new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(),
+ new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("2.2.13"),
+ new DbUpgrade[] {new Upgrade2213to2214(), new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(),
+ new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(),
+ new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(),
+ new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(),
+ new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("2.2.14"),
+ new DbUpgrade[] {new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(),
+ new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(),
+ new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(),
+ new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("3.0.0"),
+ new DbUpgrade[] {new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(),
+ new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(),
+ new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(),
+ new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("3.0.1"),
+ new DbUpgrade[] {new Upgrade301to302(), new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(),
+ new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(),
+ new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(),
+ new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("3.0.2"),
+ new DbUpgrade[] {new Upgrade302to40(), new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(),
+ new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(),
+ new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(),
+ new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.0.0"),
+ new DbUpgrade[] {new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(),
+ new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(),
+ new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(),
+ new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.0.1"),
+ new DbUpgrade[] {new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(),
+ new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(),
+ new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(),
+ new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.0.2"),
+ new DbUpgrade[] {new Upgrade40to41(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(),
+ new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(),
+ new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(),
+ new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.1.0"),
+ new DbUpgrade[] {new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(),
+ new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(),
+ new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(),
+ new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.1.1"),
+ new DbUpgrade[] {new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(),
+ new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(),
+ new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(),
+ new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.2.0"),
+ new DbUpgrade[] {new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(),
+ new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(),
+ new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(),
+ new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.2.1"),
+ new DbUpgrade[] {new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(),
+ new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(),
+ new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.3.0"),
+ new DbUpgrade[] {new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(),
+ new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(),
+ new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.3.1"),
+ new DbUpgrade[] {new Upgrade431to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(),
+ new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(),
+ new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.3.2"),
+ new DbUpgrade[] {new Upgrade432to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(),
+ new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(),
+ new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.4.0"),
+ new DbUpgrade[] {new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(),
+ new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(),
+ new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.4.1"),
+ new DbUpgrade[] {new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(),
+ new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(),
+ new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.4.2"),
+ new DbUpgrade[] {new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(),
+ new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(),
+ new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.4.3"),
+ new DbUpgrade[] {new Upgrade443to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(),
+ new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(),
+ new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.4.4"),
+ new DbUpgrade[] {new Upgrade444to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(),
+ new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(),
+ new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.5.0"),
+ new DbUpgrade[] {new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(),
+ new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(),
+ new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.5.1"),
+ new DbUpgrade[] {new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(),
+ new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(),
+ new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.5.2"),
+ new DbUpgrade[] {new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(),
+ new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.5.3"),
+ new DbUpgrade[] {new Upgrade453to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(),
+ new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.6.0"),
+ new DbUpgrade[] {new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(),
+ new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.6.1"),
+ new DbUpgrade[] {new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(),
+ new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.6.2"),
+ new DbUpgrade[] {new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(),
+ new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.7.0"),
+ new DbUpgrade[] {new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(),
+ new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.7.1"),
+ new DbUpgrade[] {new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(),
+ new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.7.2"),
+ new DbUpgrade[] {new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(),
+ new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.8.0"),
+ new DbUpgrade[] {new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(),
+ new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.8.1"),
+ new DbUpgrade[] {new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
- _upgradeMap.put(CloudStackVersion.parse("4.3.0"), new DbUpgrade[] {new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
+ _upgradeMap.put(CloudStackVersion.parse("4.8.2.0"),
+ new DbUpgrade[] {new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("4.9.0"),
+ new DbUpgrade[] {new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
- _upgradeMap.put(CloudStackVersion.parse("4.3.1"), new DbUpgrade[] {new Upgrade431to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
+ _upgradeMap.put(CloudStackVersion.parse("4.9.1.0"),
+ new DbUpgrade[] {new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
- _upgradeMap.put(CloudStackVersion.parse("4.3.2"), new DbUpgrade[] {new Upgrade432to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
+ _upgradeMap.put(CloudStackVersion.parse("4.9.2.0"),
+ new DbUpgrade[] {new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
- _upgradeMap.put(CloudStackVersion.parse("4.4.0"), new DbUpgrade[] {new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
+ _upgradeMap.put(CloudStackVersion.parse("4.9.3.0"),
+ new DbUpgrade[] {new Upgrade4930to41000(), new Upgrade41000to41100()});
- _upgradeMap.put(CloudStackVersion.parse("4.4.1"), new DbUpgrade[] {new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000() });
-
- _upgradeMap.put(CloudStackVersion.parse("4.4.2"), new DbUpgrade[] {new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.4.3"), new DbUpgrade[] {new Upgrade443to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.4.4"), new DbUpgrade[] {new Upgrade444to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.5.0"), new DbUpgrade[] {new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.5.1"), new DbUpgrade[] {new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.5.2"), new DbUpgrade[] {new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.5.3"), new DbUpgrade[] {new Upgrade453to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.6.0"), new DbUpgrade[] {new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.6.1"), new DbUpgrade[] {new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.6.2"), new DbUpgrade[] {new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.7.0"), new DbUpgrade[] {new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.7.1"), new DbUpgrade[] {new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.7.2"), new DbUpgrade[] {new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.8.0"), new DbUpgrade[] {new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.8.1"), new DbUpgrade[] {new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.8.2.0"), new DbUpgrade[] {new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.9.0"), new DbUpgrade[] {new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.9.1.0"), new DbUpgrade[] {new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.9.2.0"), new DbUpgrade[] {new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("4.9.3.0"), new DbUpgrade[] {new Upgrade4930to41000()});
+ _upgradeMap.put(CloudStackVersion.parse("4.10.0.0"),
+ new DbUpgrade[] {new Upgrade41000to41100()});
//CP Upgrades
- _upgradeMap.put(CloudStackVersion.parse("3.0.3"), new DbUpgrade[] {new Upgrade303to304(), new Upgrade304to305(), new Upgrade305to306(), new Upgrade306to307(), new Upgrade307to410(),
- new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("3.0.4"), new DbUpgrade[] {new Upgrade304to305(), new Upgrade305to306(), new Upgrade306to307(), new Upgrade307to410(), new Upgrade410to420(),
- new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("3.0.5"), new DbUpgrade[] {new Upgrade305to306(), new Upgrade306to307(), new Upgrade307to410(), new Upgrade410to420(), new Upgrade420to421(),
- new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("3.0.6"), new DbUpgrade[] {new Upgrade306to307(), new Upgrade307to410(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(),
- new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("3.0.7"), new DbUpgrade[] {new Upgrade307to410(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("2.2.15"), new DbUpgrade[] {new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(),
- new Upgrade302to303(), new Upgrade303to304(), new Upgrade304to305(), new Upgrade305to306(), new Upgrade306to307(), new Upgrade307to410(),
- new Upgrade410to420(),
- new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
-
- _upgradeMap.put(CloudStackVersion.parse("2.2.16"), new DbUpgrade[] {new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(),
- new Upgrade302to303(), new Upgrade303to304(), new Upgrade304to305(), new Upgrade305to306(), new Upgrade306to307(), new Upgrade307to410(),
- new Upgrade410to420(),
- new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000()});
+ _upgradeMap.put(CloudStackVersion.parse("3.0.3"),
+ new DbUpgrade[] {new Upgrade303to304(), new Upgrade304to305(), new Upgrade305to306(), new Upgrade306to307(), new Upgrade307to410(), new Upgrade410to420(),
+ new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(),
+ new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(),
+ new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("3.0.4"),
+ new DbUpgrade[] {new Upgrade304to305(), new Upgrade305to306(), new Upgrade306to307(), new Upgrade307to410(), new Upgrade410to420(), new Upgrade420to421(),
+ new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(),
+ new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(),
+ new Upgrade490to4910(), new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("3.0.5"),
+ new DbUpgrade[] {new Upgrade305to306(), new Upgrade306to307(), new Upgrade307to410(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(),
+ new Upgrade430to440(), new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(),
+ new Upgrade460to461(), new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(),
+ new Upgrade4910to4920(), new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("3.0.6"),
+ new DbUpgrade[] {new Upgrade306to307(), new Upgrade307to410(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(),
+ new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(),
+ new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(),
+ new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("3.0.7"),
+ new DbUpgrade[] {new Upgrade307to410(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(), new Upgrade440to441(),
+ new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(), new Upgrade461to470(),
+ new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(),
+ new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("2.2.15"),
+ new DbUpgrade[] {new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to303(), new Upgrade303to304(), new Upgrade304to305(),
+ new Upgrade305to306(), new Upgrade306to307(), new Upgrade307to410(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(),
+ new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(),
+ new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(),
+ new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
+
+ _upgradeMap.put(CloudStackVersion.parse("2.2.16"),
+ new DbUpgrade[] {new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to303(), new Upgrade303to304(), new Upgrade304to305(),
+ new Upgrade305to306(), new Upgrade306to307(), new Upgrade307to410(), new Upgrade410to420(), new Upgrade420to421(), new Upgrade421to430(), new Upgrade430to440(),
+ new Upgrade440to441(), new Upgrade441to442(), new Upgrade442to450(), new Upgrade450to451(), new Upgrade451to452(), new Upgrade452to460(), new Upgrade460to461(),
+ new Upgrade461to470(), new Upgrade470to471(), new Upgrade471to480(), new Upgrade480to481(), new Upgrade481to490(), new Upgrade490to4910(), new Upgrade4910to4920(),
+ new Upgrade4920to4930(), new Upgrade4930to41000(), new Upgrade41000to41100()});
final List<CloudStackVersion> sortedVersions = newArrayList(_upgradeMap.keySet());
sort(sortedVersions);
@@ -317,7 +455,7 @@ public DatabaseUpgradeChecker() {
protected void runScript(Connection conn, File file) {
- try(FileReader reader = new FileReader(file);) {
+ try (FileReader reader = new FileReader(file);) {
ScriptRunner runner = new ScriptRunner(conn, false, true);
runner.runScript(reader);
} catch (FileNotFoundException e) {
@@ -368,12 +506,11 @@ protected void runScript(Connection conn, File file) {
checkArgument(currentVersion != null);
checkArgument(currentVersion.compareTo(dbVersion) > 0);
- final DbUpgrade[] upgrades = _upgradeMap.containsKey(dbVersion) ? _upgradeMap.get(dbVersion) :
- findMostRecentUpgradePath(dbVersion);
+ final DbUpgrade[] upgrades = _upgradeMap.containsKey(dbVersion) ? _upgradeMap.get(dbVersion) : findMostRecentUpgradePath(dbVersion);
// When there is no upgrade defined for the target version, we assume that there were no schema changes or
// data migrations required. Based on that assumption, we add a noop DbUpgrade to the end of the list ...
- final CloudStackVersion tailVersion = upgrades.length > 0 ? CloudStackVersion.parse(upgrades[upgrades.length-1].getUpgradedVersion()) : dbVersion;
+ final CloudStackVersion tailVersion = upgrades.length > 0 ? CloudStackVersion.parse(upgrades[upgrades.length - 1].getUpgradedVersion()) : dbVersion;
if (currentVersion.compareTo(tailVersion) != 0) {
return concat(upgrades, new NoopDbUpgrade(tailVersion, currentVersion));
@@ -398,16 +535,15 @@ protected void upgrade(CloudStackVersion dbVersion, CloudStackVersion currentVer
if (!supportsRollingUpgrade && false) { // FIXME: Needs to detect if there are management servers running
// ClusterManagerImpl.arePeersRunning(null)) {
- String errorMessage =
- "Unable to run upgrade because the upgrade sequence does not support rolling update and there are other management server nodes running";
+ String errorMessage = "Unable to run upgrade because the upgrade sequence does not support rolling update and there are other management server nodes running";
s_logger.error(errorMessage);
throw new CloudRuntimeException(errorMessage);
}
for (DbUpgrade upgrade : upgrades) {
VersionVO version;
- s_logger.debug("Running upgrade " + upgrade.getClass().getSimpleName() + " to upgrade from " + upgrade.getUpgradableVersionRange()[0] + "-" +
- upgrade.getUpgradableVersionRange()[1] + " to " + upgrade.getUpgradedVersion());
+ s_logger.debug("Running upgrade " + upgrade.getClass().getSimpleName() + " to upgrade from " + upgrade.getUpgradableVersionRange()[0] + "-" + upgrade
+ .getUpgradableVersionRange()[1] + " to " + upgrade.getUpgradedVersion());
TransactionLegacy txn = TransactionLegacy.open("Upgrade");
txn.start();
try {
@@ -443,8 +579,8 @@ protected void upgrade(CloudStackVersion dbVersion, CloudStackVersion currentVer
// Run the corresponding '-cleanup.sql' script
txn = TransactionLegacy.open("Cleanup");
try {
- s_logger.info("Cleanup upgrade " + upgrade.getClass().getSimpleName() + " to upgrade from " + upgrade.getUpgradableVersionRange()[0] + "-" +
- upgrade.getUpgradableVersionRange()[1] + " to " + upgrade.getUpgradedVersion());
+ s_logger.info("Cleanup upgrade " + upgrade.getClass().getSimpleName() + " to upgrade from " + upgrade.getUpgradableVersionRange()[0] + "-" + upgrade
+ .getUpgradableVersionRange()[1] + " to " + upgrade.getUpgradedVersion());
txn.start();
Connection conn;
@@ -525,7 +661,7 @@ private NoopDbUpgrade(final CloudStackVersion fromVersion, final CloudStackVersi
super();
upgradedVersion = toVersion.toString();
- upgradeRange = new String[] { fromVersion.toString(), toVersion.toString() };
+ upgradeRange = new String[] {fromVersion.toString(), toVersion.toString()};
}
diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade41000to41100.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade41000to41100.java
new file mode 100644
index 00000000000..0189ce8c627
--- /dev/null
+++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade41000to41100.java
@@ -0,0 +1,66 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package com.cloud.upgrade.dao;
+
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.script.Script;
+import org.apache.log4j.Logger;
+
+import java.io.File;
+import java.sql.Connection;
+
+public class Upgrade41000to41100 implements DbUpgrade {
+ final static Logger LOG = Logger.getLogger(Upgrade41000to41100.class);
+
+ @Override
+ public String[] getUpgradableVersionRange() {
+ return new String[] {"4.10.0.0", "4.11.0.0"};
+ }
+
+ @Override
+ public String getUpgradedVersion() {
+ return "4.11.0.0";
+ }
+
+ @Override
+ public boolean supportsRollingUpgrade() {
+ return false;
+ }
+
+ @Override
+ public File[] getPrepareScripts() {
+ String script = Script.findScript("", "db/schema-41000to41100.sql");
+ if (script == null) {
+ throw new CloudRuntimeException("Unable to find db/schema-41000to41100.sql");
+ }
+ return new File[] {new File(script)};
+ }
+
+ @Override
+ public void performDataMigration(Connection conn) {
+ }
+
+ @Override
+ public File[] getCleanupScripts() {
+ String script = Script.findScript("", "db/schema-41000to41100-cleanup.sql");
+ if (script == null) {
+ throw new CloudRuntimeException("Unable to find db/schema-41000to41100-cleanup.sql");
+ }
+ return new File[] {new File(script)};
+ }
+}
diff --git a/engine/schema/src/com/cloud/vm/VMInstanceVO.java b/engine/schema/src/com/cloud/vm/VMInstanceVO.java
index d4b18d078e4..b55e030620b 100644
--- a/engine/schema/src/com/cloud/vm/VMInstanceVO.java
+++ b/engine/schema/src/com/cloud/vm/VMInstanceVO.java
@@ -16,11 +16,14 @@
// under the License.
package com.cloud.vm;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.util.Date;
-import java.util.Map;
-import java.util.UUID;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.utils.db.Encrypt;
+import com.cloud.utils.db.GenericDao;
+import com.cloud.utils.db.StateMachine;
+import com.cloud.utils.fsm.FiniteStateObject;
+import com.cloud.vm.VirtualMachine.State;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.log4j.Logger;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
@@ -36,16 +39,11 @@
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
-
-import org.apache.commons.codec.binary.Base64;
-import org.apache.log4j.Logger;
-
-import com.cloud.hypervisor.Hypervisor.HypervisorType;
-import com.cloud.utils.db.Encrypt;
-import com.cloud.utils.db.GenericDao;
-import com.cloud.utils.db.StateMachine;
-import com.cloud.utils.fsm.FiniteStateObject;
-import com.cloud.vm.VirtualMachine.State;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Date;
+import java.util.Map;
+import java.util.UUID;
@Entity
@Table(name = "vm_instance")
@@ -566,4 +564,9 @@ public Long getPowerHostId() {
public void setPowerHostId(Long hostId) {
powerHostId = hostId;
}
+
+ @Override
+ public PartitionType partitionType() {
+ return PartitionType.VM;
+ }
}
diff --git a/engine/schema/src/com/cloud/vm/dao/NicDao.java b/engine/schema/src/com/cloud/vm/dao/NicDao.java
index d31a165955f..0d86964974a 100644
--- a/engine/schema/src/com/cloud/vm/dao/NicDao.java
+++ b/engine/schema/src/com/cloud/vm/dao/NicDao.java
@@ -44,6 +44,8 @@
NicVO findByIp4AddressAndNetworkId(String ip4Address, long networkId);
+ NicVO findByNetworkIdAndMacAddress(long networkId, String mac);
+
NicVO findDefaultNicForVM(long instanceId);
/**
@@ -77,5 +79,7 @@
NicVO getControlNicForVM(long vmId);
+ Long getPeerRouterId(String publicMacAddress, long routerId);
+
List<NicVO> listByVmIdAndKeyword(long instanceId, String keyword);
}
diff --git a/engine/schema/src/com/cloud/vm/dao/NicDaoImpl.java b/engine/schema/src/com/cloud/vm/dao/NicDaoImpl.java
index a5edf581f2b..f953a4c1f93 100644
--- a/engine/schema/src/com/cloud/vm/dao/NicDaoImpl.java
+++ b/engine/schema/src/com/cloud/vm/dao/NicDaoImpl.java
@@ -45,6 +45,7 @@
private SearchBuilder<NicVO> NonReleasedSearch;
private GenericSearchBuilder<NicVO, Integer> deviceIdSearch;
private GenericSearchBuilder<NicVO, Integer> CountByForStartingVms;
+ private SearchBuilder<NicVO> PeerRouterSearch;
@Inject
VMInstanceDao _vmDao;
@@ -67,6 +68,7 @@ protected void init() {
AllFieldsSearch.and("nicid", AllFieldsSearch.entity().getId(), Op.EQ);
AllFieldsSearch.and("strategy", AllFieldsSearch.entity().getReservationStrategy(), Op.EQ);
AllFieldsSearch.and("reserverName",AllFieldsSearch.entity().getReserver(),Op.EQ);
+ AllFieldsSearch.and("macAddress", AllFieldsSearch.entity().getMacAddress(), Op.EQ);
AllFieldsSearch.done();
IpSearch = createSearchBuilder(String.class);
@@ -94,6 +96,12 @@ protected void init() {
join1.and("state", join1.entity().getState(), Op.EQ);
CountByForStartingVms.join("vm", join1, CountByForStartingVms.entity().getInstanceId(), join1.entity().getId(), JoinBuilder.JoinType.INNER);
CountByForStartingVms.done();
+
+ PeerRouterSearch = createSearchBuilder();
+ PeerRouterSearch.and("instanceId", PeerRouterSearch.entity().getInstanceId(), Op.NEQ);
+ PeerRouterSearch.and("macAddress", PeerRouterSearch.entity().getMacAddress(), Op.EQ);
+ PeerRouterSearch.and("vmType", PeerRouterSearch.entity().getVmType(), Op.EQ);
+ PeerRouterSearch.done();
}
@Override
@@ -191,6 +199,14 @@ public NicVO findByIp4AddressAndNetworkId(String ip4Address, long networkId) {
return findOneBy(sc);
}
+ @Override
+ public NicVO findByNetworkIdAndMacAddress(long networkId, String mac) {
+ SearchCriteria<NicVO> sc = AllFieldsSearch.create();
+ sc.setParameters("network", networkId);
+ sc.setParameters("macAddress", mac);
+ return findOneBy(sc);
+ }
+
@Override
public NicVO findDefaultNicForVM(long instanceId) {
SearchCriteria<NicVO> sc = AllFieldsSearch.create();
@@ -312,6 +328,19 @@ public int countNicsForStartingVms(long networkId) {
return results.get(0);
}
+ @Override
+ public Long getPeerRouterId(String publicMacAddress, final long routerId) {
+ final SearchCriteria<NicVO> sc = PeerRouterSearch.create();
+ sc.setParameters("instanceId", routerId);
+ sc.setParameters("macAddress", publicMacAddress);
+ sc.setParameters("vmType", VirtualMachine.Type.DomainRouter);
+ NicVO nicVo = findOneBy(sc);
+ if (nicVo != null) {
+ return nicVo.getInstanceId();
+ }
+ return null;
+ }
+
@Override
public List<NicVO> listByVmIdAndKeyword(long instanceId, String keyword) {
SearchCriteria<NicVO> sc = AllFieldsSearch.create();
diff --git a/engine/schema/src/com/cloud/vm/dao/NicSecondaryIpDao.java b/engine/schema/src/com/cloud/vm/dao/NicSecondaryIpDao.java
index 2a0f751b404..ef8df516e9f 100644
--- a/engine/schema/src/com/cloud/vm/dao/NicSecondaryIpDao.java
+++ b/engine/schema/src/com/cloud/vm/dao/NicSecondaryIpDao.java
@@ -48,6 +48,8 @@
NicSecondaryIpVO findByIp4AddressAndNicId(String ip4Address, long nicId);
+ NicSecondaryIpVO findByIp4AddressAndInstanceId(Long vmId, String vmIp);
+
NicSecondaryIpVO findByIp4AddressAndNetworkIdAndInstanceId(long networkId, Long vmId, String vmIp);
List<String> getSecondaryIpAddressesForNic(long nicId);
diff --git a/engine/schema/src/com/cloud/vm/dao/NicSecondaryIpDaoImpl.java b/engine/schema/src/com/cloud/vm/dao/NicSecondaryIpDaoImpl.java
index 55c3c8a5146..4b04ff01a6d 100644
--- a/engine/schema/src/com/cloud/vm/dao/NicSecondaryIpDaoImpl.java
+++ b/engine/schema/src/com/cloud/vm/dao/NicSecondaryIpDaoImpl.java
@@ -119,8 +119,10 @@ public NicSecondaryIpVO findByInstanceIdAndNetworkId(long networkId, long instan
@Override
public NicSecondaryIpVO findByIp4AddressAndNetworkId(String ip4Address, long networkId) {
- // TODO Auto-generated method stub
- return null;
+ SearchCriteria<NicSecondaryIpVO> sc = AllFieldsSearch.create();
+ sc.setParameters("network", networkId);
+ sc.setParameters("address", ip4Address);
+ return findOneBy(sc);
}
@Override
@@ -131,6 +133,14 @@ public NicSecondaryIpVO findByIp4AddressAndNicId(String ip4Address, long nicId)
return findOneBy(sc);
}
+ @Override
+ public NicSecondaryIpVO findByIp4AddressAndInstanceId(Long vmId, String vmIp) {
+ SearchCriteria<NicSecondaryIpVO> sc = AllFieldsSearch.create();
+ sc.setParameters("instanceId", vmId);
+ sc.setParameters("address", vmIp);
+ return findOneBy(sc);
+ }
+
@Override
public NicSecondaryIpVO findByIp4AddressAndNetworkIdAndInstanceId(long networkId, Long vmId, String vmIp) {
SearchCriteria<NicSecondaryIpVO> sc = AllFieldsSearch.create();
diff --git a/engine/schema/src/com/cloud/vm/dao/VMInstanceDao.java b/engine/schema/src/com/cloud/vm/dao/VMInstanceDao.java
index 8d457fadff5..3c5024b833e 100644
--- a/engine/schema/src/com/cloud/vm/dao/VMInstanceDao.java
+++ b/engine/schema/src/com/cloud/vm/dao/VMInstanceDao.java
@@ -116,6 +116,8 @@
Long countRunningByAccount(long accountId);
+ Long countByZoneAndState(long zoneId, State state);
+
List<VMInstanceVO> listNonRemovedVmsByTypeAndNetwork(long networkId, VirtualMachine.Type... types);
/**
diff --git a/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java b/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java
index df5e60e7a1a..7065350a57e 100644
--- a/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java
+++ b/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java
@@ -87,6 +87,7 @@
protected GenericSearchBuilder<VMInstanceVO, Long> FindIdsOfVirtualRoutersByAccount;
protected GenericSearchBuilder<VMInstanceVO, Long> CountActiveByHost;
protected GenericSearchBuilder<VMInstanceVO, Long> CountRunningByAccount;
+ protected GenericSearchBuilder<VMInstanceVO, Long> CountByZoneAndState;
protected SearchBuilder<VMInstanceVO> NetworkTypeSearch;
protected GenericSearchBuilder<VMInstanceVO, String> DistinctHostNameSearch;
protected SearchBuilder<VMInstanceVO> HostAndStateSearch;
@@ -242,6 +243,12 @@ protected void init() {
CountRunningByAccount.and("state", CountRunningByAccount.entity().getState(), SearchCriteria.Op.EQ);
CountRunningByAccount.done();
+ CountByZoneAndState = createSearchBuilder(Long.class);
+ CountByZoneAndState.select(null, Func.COUNT, null);
+ CountByZoneAndState.and("zone", CountByZoneAndState.entity().getDataCenterId(), SearchCriteria.Op.EQ);
+ CountByZoneAndState.and("state", CountByZoneAndState.entity().getState(), SearchCriteria.Op.EQ);
+ CountByZoneAndState.done();
+
HostAndStateSearch = createSearchBuilder();
HostAndStateSearch.and("host", HostAndStateSearch.entity().getHostId(), Op.EQ);
HostAndStateSearch.and("states", HostAndStateSearch.entity().getState(), Op.IN);
@@ -718,6 +725,14 @@ public Long countRunningByAccount(long accountId) {
return customSearch(sc, null).get(0);
}
+ @Override
+ public Long countByZoneAndState(long zoneId, State state) {
+ SearchCriteria<Long> sc = CountByZoneAndState.create();
+ sc.setParameters("zone", zoneId);
+ sc.setParameters("state", state);
+ return customSearch(sc, null).get(0);
+ }
+
@Override
public List<VMInstanceVO> listNonRemovedVmsByTypeAndNetwork(long networkId, VirtualMachine.Type... types) {
if (NetworkTypeSearch == null) {
diff --git a/engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDao.java b/engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDao.java
index 37544919657..c9aeba1c599 100644
--- a/engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDao.java
+++ b/engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDao.java
@@ -20,6 +20,7 @@
import com.cloud.utils.db.GenericDao;
import org.apache.cloudstack.acl.Role;
import org.apache.cloudstack.acl.RolePermission;
+import org.apache.cloudstack.acl.RolePermission.Permission;
import org.apache.cloudstack.acl.RolePermissionVO;
import java.util.List;
@@ -40,6 +41,15 @@
*/
boolean update(final Role role, final List<RolePermission> newOrder);
+ /**
+ * Updates existing role permission
+ * @param role role of which rule belongs
+ * @param rolePermission role permission
+ * @param permission permission
+ * @return true on success, false if not
+ */
+ boolean update(final Role role, final RolePermission rolePermission, final Permission permission);
+
/**
* Returns ordered linked-list of role permission for a given role
* @param roleId the ID of the role
diff --git a/engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDaoImpl.java b/engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDaoImpl.java
index 8f6fa83f012..32faf4e9a8c 100644
--- a/engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDaoImpl.java
+++ b/engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDaoImpl.java
@@ -29,6 +29,7 @@
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.acl.Role;
import org.apache.cloudstack.acl.RolePermission;
+import org.apache.cloudstack.acl.RolePermission.Permission;
import org.apache.cloudstack.acl.RolePermissionVO;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@@ -149,6 +150,19 @@ public Boolean doInTransaction(TransactionStatus status) {
});
}
+ @Override
+ public boolean update(Role role, RolePermission rolePermission, Permission permission) {
+ if (role == null || rolePermission == null || permission == null) {
+ return false;
+ }
+ RolePermissionVO rolePermissionVO = findById(rolePermission.getId());
+ if (rolePermissionVO == null || role.getId() != rolePermission.getRoleId() || rolePermissionVO.getId() != rolePermission.getId()) {
+ return false;
+ }
+ rolePermissionVO.setPermission(permission);
+ return update(rolePermission.getId(), rolePermissionVO);
+ }
+
@Override
public List<RolePermissionVO> findAllByRoleIdSorted(final Long roleId) {
final SearchCriteria<RolePermissionVO> sc = RolePermissionsSearch.create();
diff --git a/engine/schema/src/org/apache/cloudstack/annotation/AnnotationVO.java b/engine/schema/src/org/apache/cloudstack/annotation/AnnotationVO.java
new file mode 100644
index 00000000000..982dd6db15b
--- /dev/null
+++ b/engine/schema/src/org/apache/cloudstack/annotation/AnnotationVO.java
@@ -0,0 +1,154 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.annotation;
+
+import com.cloud.utils.db.GenericDao;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.util.Date;
+import java.util.UUID;
+
+/**
+ * @since 4.11
+ */
+@Entity
+@Table(name = "annotations")
+public class AnnotationVO implements Annotation {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private long id;
+
+ @Column(name = "uuid")
+ private String uuid;
+
+ @Column(name = "annotation")
+ private String annotation;
+
+ @Column(name = "entity_uuid")
+ private String entityUuid;
+
+ @Column(name = "entity_type")
+ private AnnotationService.EntityType entityType;
+
+ @Column(name = "user_uuid")
+ private String userUuid;
+
+ @Column(name = GenericDao.CREATED_COLUMN)
+ private Date created;
+
+ @Column(name = GenericDao.REMOVED_COLUMN)
+ private Date removed;
+
+ // construct
+ public AnnotationVO() {
+ this.uuid = UUID.randomUUID().toString();
+ }
+
+ public AnnotationVO(String text, AnnotationService.EntityType type, String uuid) {
+ this();
+ setAnnotation(text);
+ setEntityType(type);
+ setEntityUuid(uuid);
+ }
+
+ public AnnotationVO(String text, String type, String uuid) {
+ this();
+ setAnnotation(text);
+ setEntityType(type);
+ setEntityUuid(uuid);
+ }
+ // access
+
+ @Override
+ public long getId() {
+ return id;
+ }
+
+
+ @Override
+ public String getUuid() {
+ return uuid;
+ }
+
+ @Override
+ public String getAnnotation() {
+ return annotation;
+ }
+
+ @Override
+ public String getEntityUuid() {
+ return entityUuid;
+ }
+
+ @Override
+ public AnnotationService.EntityType getEntityType() {
+ return entityType;
+ }
+
+ @Override
+ public String getUserUuid() {
+ return userUuid;
+ }
+
+ @Override
+ public Date getCreated() {
+ return created;
+ }
+
+ @Override
+ public Date getRemoved() {
+ return removed;
+ }
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
+ public void setAnnotation(String annotation) {
+ this.annotation = annotation;
+ }
+
+ public void setEntityUuid(String entityUuid) {
+ this.entityUuid = entityUuid;
+ }
+
+ public void setEntityType(String entityType) {
+ this.entityType = AnnotationService.EntityType.valueOf(entityType);
+ }
+
+ public void setEntityType(AnnotationService.EntityType entityType) {
+ this.entityType = entityType;
+ }
+
+ public void setUserUuid(String userUuid) {
+ this.userUuid = userUuid;
+ }
+
+ public void setCreated(Date created) {
+ this.created = created;
+ }
+
+ public void setRemoved(Date removed) {
+ this.removed = removed;
+ }
+}
diff --git a/engine/schema/src/org/apache/cloudstack/annotation/dao/AnnotationDao.java b/engine/schema/src/org/apache/cloudstack/annotation/dao/AnnotationDao.java
new file mode 100644
index 00000000000..6bf8484560c
--- /dev/null
+++ b/engine/schema/src/org/apache/cloudstack/annotation/dao/AnnotationDao.java
@@ -0,0 +1,30 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.annotation.dao;
+
+import org.apache.cloudstack.annotation.AnnotationVO;
+import com.cloud.utils.db.GenericDao;
+
+import java.util.List;
+
+/**
+ * @since 4.11
+ */
+public interface AnnotationDao extends GenericDao<AnnotationVO, Long> {
+ public List<AnnotationVO> findByEntityType(String entityType);
+ public List<AnnotationVO> findByEntity(String entityType, String entityUuid);
+}
diff --git a/engine/schema/src/org/apache/cloudstack/annotation/dao/AnnotationDaoImpl.java b/engine/schema/src/org/apache/cloudstack/annotation/dao/AnnotationDaoImpl.java
new file mode 100644
index 00000000000..e2fcc905e0b
--- /dev/null
+++ b/engine/schema/src/org/apache/cloudstack/annotation/dao/AnnotationDaoImpl.java
@@ -0,0 +1,59 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.annotation.dao;
+
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import org.apache.cloudstack.annotation.AnnotationVO;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @since 4.1
+ */
+@Component
+public class AnnotationDaoImpl extends GenericDaoBase<AnnotationVO, Long> implements AnnotationDao {
+ private final SearchBuilder<AnnotationVO> AnnotationSearchByType;
+ private final SearchBuilder<AnnotationVO> AnnotationSearchByTypeAndUuid;
+
+ public AnnotationDaoImpl() {
+ super();
+ AnnotationSearchByType = createSearchBuilder();
+ AnnotationSearchByType.and("entityType", AnnotationSearchByType.entity().getEntityType(), SearchCriteria.Op.EQ);
+ AnnotationSearchByType.done();
+ AnnotationSearchByTypeAndUuid = createSearchBuilder();
+ AnnotationSearchByTypeAndUuid.and("entityType", AnnotationSearchByTypeAndUuid.entity().getEntityType(), SearchCriteria.Op.EQ);
+ AnnotationSearchByTypeAndUuid.and("entityUuid", AnnotationSearchByTypeAndUuid.entity().getEntityUuid(), SearchCriteria.Op.EQ);
+ AnnotationSearchByTypeAndUuid.done();
+
+ }
+
+ @Override public List<AnnotationVO> findByEntityType(String entityType) {
+ SearchCriteria<AnnotationVO> sc = createSearchCriteria();
+ sc.addAnd("entityType", SearchCriteria.Op.EQ, entityType);
+ return listBy(sc);
+ }
+
+ @Override public List<AnnotationVO> findByEntity(String entityType, String entityUuid) {
+ SearchCriteria<AnnotationVO> sc = createSearchCriteria();
+ sc.addAnd("entityType", SearchCriteria.Op.EQ, entityType);
+ sc.addAnd("entityUuid", SearchCriteria.Op.EQ, entityUuid);
+ return listBy(sc, null);
+ }
+}
diff --git a/engine/schema/src/org/apache/cloudstack/engine/cloud/entity/api/db/VMEntityVO.java b/engine/schema/src/org/apache/cloudstack/engine/cloud/entity/api/db/VMEntityVO.java
index d7560e22bd1..cdb80febdcf 100644
--- a/engine/schema/src/org/apache/cloudstack/engine/cloud/entity/api/db/VMEntityVO.java
+++ b/engine/schema/src/org/apache/cloudstack/engine/cloud/entity/api/db/VMEntityVO.java
@@ -550,4 +550,9 @@ public boolean isDisplay() {
public void setDisplay(boolean display) {
this.display = display;
}
+
+ @Override
+ public PartitionType partitionType() {
+ return PartitionType.VM;
+ }
}
diff --git a/engine/schema/src/org/apache/cloudstack/ha/HAConfigVO.java b/engine/schema/src/org/apache/cloudstack/ha/HAConfigVO.java
new file mode 100644
index 00000000000..a68ed93746d
--- /dev/null
+++ b/engine/schema/src/org/apache/cloudstack/ha/HAConfigVO.java
@@ -0,0 +1,142 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ha;
+
+import com.cloud.utils.db.StateMachine;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import java.util.Date;
+
+@Entity
+@Table(name = "ha_config")
+public class HAConfigVO implements HAConfig {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private Long id;
+
+ @Column(name = "resource_id", updatable = false, nullable = false)
+ private long resourceId;
+
+ @Column(name = "resource_type", nullable = false)
+ @Enumerated(value = EnumType.STRING)
+ private HAResource.ResourceType resourceType;
+
+ @Column(name = "enabled")
+ private boolean enabled = false;
+
+ // There is no setter for status because it has to be set in the dao code
+ @Enumerated(value = EnumType.STRING)
+ @StateMachine(state = HAState.class, event = HAConfig.Event.class)
+ @Column(name = "ha_state", updatable = true, nullable = false, length = 32)
+ private HAState haState = null;
+
+ @Column(name = "provider")
+ private String haProvider;
+
+ // This field should be updated every time the state is updated.
+ // There's no set method in the vo object because it is done with in the dao code.
+ @Column(name = "update_count", updatable = true, nullable = false)
+ private long updateCount;
+
+ @Column(name = "update_time", updatable = true)
+ @Temporal(value = TemporalType.TIMESTAMP)
+ private Date updateTime;
+
+ @Column(name = "mgmt_server_id")
+ private Long managementServerId;
+
+ public HAConfigVO() {
+ }
+
+ @Override
+ public long getId() {
+ return id;
+ }
+
+ public long getResourceId() {
+ return resourceId;
+ }
+
+ public HAResource.ResourceType getResourceType() {
+ return resourceType;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public long getUpdateCount() {
+ return updateCount;
+ }
+
+ public long incrUpdateCount() {
+ updateCount++;
+ return updateCount;
+ }
+
+ public Date getUpdateTime() {
+ return updateTime;
+ }
+
+ public Long getManagementServerId() {
+ return managementServerId;
+ }
+
+ public HAState getHaState() {
+ return haState;
+ }
+
+ @Override
+ public HAState getState() {
+ return haState;
+ }
+
+ public String getHaProvider() {
+ return haProvider;
+ }
+
+ public void setHaProvider(String haProvider) {
+ this.haProvider = haProvider;
+ }
+
+ public void setResourceId(long resourceId) {
+ this.resourceId = resourceId;
+ }
+
+ public void setResourceType(HAResource.ResourceType resourceType) {
+ this.resourceType = resourceType;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public void setManagementServerId(Long managementServerId) {
+ this.managementServerId = managementServerId;
+ }
+}
diff --git a/engine/schema/src/org/apache/cloudstack/ha/dao/HAConfigDao.java b/engine/schema/src/org/apache/cloudstack/ha/dao/HAConfigDao.java
new file mode 100644
index 00000000000..4a398f821a9
--- /dev/null
+++ b/engine/schema/src/org/apache/cloudstack/ha/dao/HAConfigDao.java
@@ -0,0 +1,32 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ha.dao;
+
+import com.cloud.utils.db.GenericDao;
+import com.cloud.utils.fsm.StateDao;
+import org.apache.cloudstack.ha.HAConfig;
+import org.apache.cloudstack.ha.HAConfigVO;
+import org.apache.cloudstack.ha.HAResource;
+
+import java.util.List;
+
+public interface HAConfigDao extends GenericDao<HAConfigVO, Long>, StateDao<HAConfig.HAState, HAConfig.Event, HAConfig> {
+ HAConfig findHAResource(long resourceId, HAResource.ResourceType resourceType);
+ List<HAConfig> listHAResource(final Long resourceId, final HAResource.ResourceType resourceType);
+ void expireServerOwnership(long serverId);
+}
\ No newline at end of file
diff --git a/engine/schema/src/org/apache/cloudstack/ha/dao/HAConfigDaoImpl.java b/engine/schema/src/org/apache/cloudstack/ha/dao/HAConfigDaoImpl.java
new file mode 100644
index 00000000000..4d74e2e6656
--- /dev/null
+++ b/engine/schema/src/org/apache/cloudstack/ha/dao/HAConfigDaoImpl.java
@@ -0,0 +1,149 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ha.dao;
+
+import com.cloud.utils.DateUtil;
+import com.cloud.utils.db.Attribute;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.db.TransactionCallbackNoReturn;
+import com.cloud.utils.db.TransactionLegacy;
+import com.cloud.utils.db.TransactionStatus;
+import com.cloud.utils.db.UpdateBuilder;
+import org.apache.cloudstack.ha.HAConfig;
+import org.apache.cloudstack.ha.HAConfigVO;
+import org.apache.cloudstack.ha.HAResource;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+@DB
+@Component
+public class HAConfigDaoImpl extends GenericDaoBase<HAConfigVO, Long> implements HAConfigDao {
+ private static final Logger LOG = Logger.getLogger(HAConfigDaoImpl.class);
+
+ private static final String EXPIRE_OWNERSHIP = "UPDATE ha_config set mgmt_server_id=NULL where mgmt_server_id=?";
+
+ private SearchBuilder<HAConfigVO> ResourceSearch;
+ private SearchBuilder<HAConfigVO> StateUpdateSearch;
+
+ private Attribute HAStateAttr;
+ private Attribute MsIdAttr;
+ private Attribute UpdateTimeAttr;
+
+ public HAConfigDaoImpl() {
+ super();
+
+ ResourceSearch = createSearchBuilder();
+ ResourceSearch.and("resourceId", ResourceSearch.entity().getResourceId(), SearchCriteria.Op.EQ);
+ ResourceSearch.and("resourceType", ResourceSearch.entity().getResourceType(), SearchCriteria.Op.EQ);
+ ResourceSearch.done();
+
+ StateUpdateSearch = createSearchBuilder();
+ StateUpdateSearch.and("id", StateUpdateSearch.entity().getId(), SearchCriteria.Op.EQ);
+ StateUpdateSearch.and("haState", StateUpdateSearch.entity().getHaState(), SearchCriteria.Op.EQ);
+ StateUpdateSearch.and("update", StateUpdateSearch.entity().getUpdateCount(), SearchCriteria.Op.EQ);
+ StateUpdateSearch.done();
+
+ HAStateAttr = _allAttributes.get("haState");
+ MsIdAttr = _allAttributes.get("managementServerId");
+ UpdateTimeAttr = _allAttributes.get("updateTime");
+ assert (HAStateAttr != null && MsIdAttr != null && UpdateTimeAttr != null) : "Couldn't find one of these attributes";
+ }
+
+ @Override
+ public boolean updateState(HAConfig.HAState currentState, HAConfig.Event event, HAConfig.HAState nextState, HAConfig vo, Object data) {
+ HAConfigVO haConfig = (HAConfigVO) vo;
+ if (haConfig == null) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Invalid ha config view object provided");
+ }
+ return false;
+ }
+
+ Long newManagementServerId = event.getServerId();
+ if (currentState == nextState && (haConfig.getManagementServerId() != null && haConfig.getManagementServerId().equals(newManagementServerId))) {
+ return false;
+ }
+
+ if (event == HAConfig.Event.Disabled) {
+ newManagementServerId = null;
+ }
+
+ SearchCriteria<HAConfigVO> sc = StateUpdateSearch.create();
+ sc.setParameters("id", haConfig.getId());
+ sc.setParameters("haState", currentState);
+ sc.setParameters("update", haConfig.getUpdateCount());
+
+ haConfig.incrUpdateCount();
+ UpdateBuilder ub = getUpdateBuilder(haConfig);
+ ub.set(haConfig, HAStateAttr, nextState);
+ ub.set(haConfig, UpdateTimeAttr, DateUtil.currentGMTTime());
+ ub.set(haConfig, MsIdAttr, newManagementServerId);
+
+ int result = update(ub, sc, null);
+ if (LOG.isTraceEnabled() && result <= 0) {
+ LOG.trace(String.format("Failed to update HA state from:%s to:%s due to event:%s for the ha_config id:%d", currentState, nextState, event, haConfig.getId()));
+ }
+ return result > 0;
+ }
+
+ @Override
+ public HAConfig findHAResource(final long resourceId, final HAResource.ResourceType resourceType) {
+ final SearchCriteria<HAConfigVO> sc = ResourceSearch.create();
+ sc.setParameters("resourceId", resourceId);
+ sc.setParameters("resourceType", resourceType);
+ return findOneBy(sc);
+ }
+
+ @Override
+ public List<HAConfig> listHAResource(final Long resourceId, final HAResource.ResourceType resourceType) {
+ final SearchCriteria<HAConfigVO> sc = ResourceSearch.create();
+ if (resourceId != null && resourceId > 0L) {
+ sc.setParameters("resourceId", resourceId);
+ }
+ if (resourceType != null) {
+ sc.setParameters("resourceType", resourceType);
+ }
+ return new ArrayList<HAConfig>(listBy(sc));
+ }
+
+ @Override
+ public void expireServerOwnership(final long serverId) {
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ TransactionLegacy txn = TransactionLegacy.currentTxn();
+ try (final PreparedStatement pstmt = txn.prepareAutoCloseStatement(EXPIRE_OWNERSHIP);) {
+ pstmt.setLong(1, serverId);
+ pstmt.executeUpdate();
+ } catch (SQLException e) {
+ txn.rollback();
+ LOG.warn("Failed to expire HA ownership of management server id: " + serverId);
+ }
+ }
+ });
+ }
+}
diff --git a/engine/schema/src/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementVO.java b/engine/schema/src/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementVO.java
index b5c357c3f82..2f975caf0f1 100644
--- a/engine/schema/src/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementVO.java
+++ b/engine/schema/src/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementVO.java
@@ -59,7 +59,7 @@
private String address;
@Column(name = "port")
- private Integer port;
+ private String port;
@Column(name = "username")
private String username;
@@ -121,7 +121,7 @@ public String getAddress() {
}
@Override
- public Integer getPort() {
+ public String getPort() {
return port;
}
@@ -173,7 +173,7 @@ public void setAddress(String address) {
}
@Override
- public void setPort(Integer port) {
+ public void setPort(String port) {
this.port = port;
}
diff --git a/engine/schema/src/org/apache/cloudstack/outofbandmanagement/dao/OutOfBandManagementDao.java b/engine/schema/src/org/apache/cloudstack/outofbandmanagement/dao/OutOfBandManagementDao.java
index 5985b816256..8a4ee36710f 100644
--- a/engine/schema/src/org/apache/cloudstack/outofbandmanagement/dao/OutOfBandManagementDao.java
+++ b/engine/schema/src/org/apache/cloudstack/outofbandmanagement/dao/OutOfBandManagementDao.java
@@ -27,5 +27,5 @@
public interface OutOfBandManagementDao extends GenericDao<OutOfBandManagementVO, Long>, StateDao<OutOfBandManagement.PowerState, OutOfBandManagement.PowerState.Event, OutOfBandManagement> {
OutOfBandManagement findByHost(long hostId);
List<OutOfBandManagementVO> findAllByManagementServer(long serverId);
- void expireOutOfBandManagementOwnershipByServer(long serverId);
+ void expireServerOwnership(long serverId);
}
diff --git a/engine/schema/src/org/apache/cloudstack/outofbandmanagement/dao/OutOfBandManagementDaoImpl.java b/engine/schema/src/org/apache/cloudstack/outofbandmanagement/dao/OutOfBandManagementDaoImpl.java
index b914b6b702d..3cdd28fe25a 100644
--- a/engine/schema/src/org/apache/cloudstack/outofbandmanagement/dao/OutOfBandManagementDaoImpl.java
+++ b/engine/schema/src/org/apache/cloudstack/outofbandmanagement/dao/OutOfBandManagementDaoImpl.java
@@ -110,7 +110,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
}
@Override
- public void expireOutOfBandManagementOwnershipByServer(long serverId) {
+ public void expireServerOwnership(long serverId) {
final String resetOwnerSql = "UPDATE oobm set mgmt_server_id=NULL, power_state=NULL where mgmt_server_id=?";
executeExpireOwnershipSql(resetOwnerSql, serverId);
if (LOG.isDebugEnabled()) {
diff --git a/engine/schema/test/resources/db.properties b/engine/schema/test/resources/db.properties
index 49fd68aa933..5571ad9cc96 100644
--- a/engine/schema/test/resources/db.properties
+++ b/engine/schema/test/resources/db.properties
@@ -19,7 +19,7 @@
# management server clustering parameters, change cluster.node.IP to the machine IP address
-# in which the management server(Tomcat) is running
+# in which the management server is running
cluster.node.IP=127.0.0.1
cluster.servlet.port=9090
region.id=1
diff --git a/engine/service/pom.xml b/engine/service/pom.xml
index 3adbb0ba4e9..a14e995ebf6 100644
--- a/engine/service/pom.xml
+++ b/engine/service/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
</parent>
<artifactId>cloud-engine-service</artifactId>
<packaging>war</packaging>
diff --git a/engine/service/src/main/webapp/WEB-INF/log4j.xml b/engine/service/src/main/webapp/WEB-INF/log4j.xml
index df46461f972..19d48b47e83 100644
--- a/engine/service/src/main/webapp/WEB-INF/log4j.xml
+++ b/engine/service/src/main/webapp/WEB-INF/log4j.xml
@@ -25,17 +25,7 @@
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
</layout>
</appender>
-<!--
- <appender name="FILE_APPENDER" class="org.apache.log4j.DailyRollingFileAppender">
- <param name="File" value="${catalina.home}/logs/webapp.txt"/>
- <param name="DatePattern" value="'-'yyyy-MM-dd'.txt'"/>
- <param name="Threshold" value="DEBUG"/>
- <layout class="org.apache.log4j.PatternLayout">
- <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-4p [%t] %C{2} - %m%n"/>
- </layout>
- </appender>
- -->
-
+
<!-- Spring -->
<logger name="org.springframework" additivity="false">
<level value="DEBUG"/>
@@ -46,4 +36,4 @@
<level value="DEBUG"/>
<appender-ref ref="CONSOLE"/>
</root>
-</log4j:configuration>
\ No newline at end of file
+</log4j:configuration>
diff --git a/engine/service/src/main/webapp/WEB-INF/web.xml b/engine/service/src/main/webapp/WEB-INF/web.xml
index c5bb44f0f15..e7663cea39e 100644
--- a/engine/service/src/main/webapp/WEB-INF/web.xml
+++ b/engine/service/src/main/webapp/WEB-INF/web.xml
@@ -31,9 +31,6 @@
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
- <listener>
- <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
- </listener>
<servlet>
<display-name>CXF Servlet</display-name>
<servlet-name>CXFServlet</servlet-name>
diff --git a/engine/storage/cache/pom.xml b/engine/storage/cache/pom.xml
index 6bb3faeb89d..5cc6ffafac6 100644
--- a/engine/storage/cache/pom.xml
+++ b/engine/storage/cache/pom.xml
@@ -15,7 +15,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/engine/storage/datamotion/pom.xml b/engine/storage/datamotion/pom.xml
index 91494aa6051..5b7346cdd6b 100644
--- a/engine/storage/datamotion/pom.xml
+++ b/engine/storage/datamotion/pom.xml
@@ -16,7 +16,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
index 57e4181aaf9..7a1daba910d 100644
--- a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
+++ b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
@@ -520,10 +520,10 @@ protected Answer copySnapshot(DataObject srcData, DataObject destData) {
DataObject cacheData = null;
SnapshotInfo snapshotInfo = (SnapshotInfo)srcData;
- Object payload = snapshotInfo.getPayload();
+ Boolean snapshotFullBackup = snapshotInfo.getFullBackup();
Boolean fullSnapshot = true;
- if (payload != null) {
- fullSnapshot = (Boolean)payload;
+ if (snapshotFullBackup != null) {
+ fullSnapshot = snapshotFullBackup;
}
Map<String, String> options = new HashMap<String, String>();
options.put("fullSnapshot", fullSnapshot.toString());
diff --git a/engine/storage/image/pom.xml b/engine/storage/image/pom.xml
index d194487e14a..d49f336ad68 100644
--- a/engine/storage/image/pom.xml
+++ b/engine/storage/image/pom.xml
@@ -16,7 +16,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageStoreImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageStoreImpl.java
index 182a8ec4cab..41ce5a230b0 100644
--- a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageStoreImpl.java
+++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageStoreImpl.java
@@ -180,6 +180,11 @@ public String getProtocol() {
return imageDataStoreVO.getProtocol();
}
+ @Override
+ public String getUrl() {
+ return imageDataStoreVO.getUrl();
+ }
+
@Override
public DataStoreTO getTO() {
DataStoreTO to = getDriver().getStoreTO(this);
diff --git a/engine/storage/integration-test/pom.xml b/engine/storage/integration-test/pom.xml
index 60b7dda8ecc..26f0f24332f 100644
--- a/engine/storage/integration-test/pom.xml
+++ b/engine/storage/integration-test/pom.xml
@@ -16,7 +16,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/engine/storage/integration-test/test/resource/fakeDriverTestContext.xml b/engine/storage/integration-test/test/resource/fakeDriverTestContext.xml
index 48a99e64355..944196da1fc 100644
--- a/engine/storage/integration-test/test/resource/fakeDriverTestContext.xml
+++ b/engine/storage/integration-test/test/resource/fakeDriverTestContext.xml
@@ -43,7 +43,6 @@
<bean id="objectInDataStoreDaoImpl" class="org.apache.cloudstack.storage.db.ObjectInDataStoreDaoImpl" />
<bean id="primaryDataStoreDaoImpl" class="org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDaoImpl" />
<bean id="primaryDataStoreDetailsDaoImpl" class="org.apache.cloudstack.storage.volume.db.PrimaryDataStoreDetailsDaoImpl" />
- <bean id="templatePrimaryDataStoreDaoImpl" class="org.apache.cloudstack.storage.volume.db.TemplatePrimaryDataStoreDaoImpl" />
<bean id="LocalStoragePoolAllocator" class="org.apache.cloudstack.storage.allocator.LocalStoragePoolAllocator"/>
<bean id="clusterScopeStoragePoolAllocator" class="org.apache.cloudstack.storage.allocator.ClusterScopeStoragePoolAllocator" />
<bean id="zoneWideStoragePoolAllocator" class="org.apache.cloudstack.storage.allocator.ZoneWideStoragePoolAllocator" />
diff --git a/engine/storage/integration-test/test/resources/storageContext.xml b/engine/storage/integration-test/test/resources/storageContext.xml
index 9154edafb95..abf08767d9d 100644
--- a/engine/storage/integration-test/test/resources/storageContext.xml
+++ b/engine/storage/integration-test/test/resources/storageContext.xml
@@ -43,7 +43,6 @@
<bean id="objectInDataStoreDaoImpl" class="org.apache.cloudstack.storage.db.ObjectInDataStoreDaoImpl" />
<bean id="primaryDataStoreDaoImpl" class="org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDaoImpl" />
<bean id="primaryDataStoreDetailsDaoImpl" class="org.apache.cloudstack.storage.volume.db.PrimaryDataStoreDetailsDaoImpl" />
- <bean id="templatePrimaryDataStoreDaoImpl" class="org.apache.cloudstack.storage.volume.db.TemplatePrimaryDataStoreDaoImpl" />
<bean id="LocalStoragePoolAllocator" class="org.apache.cloudstack.storage.allocator.LocalStoragePoolAllocator"/>
<bean id="clusterScopeStoragePoolAllocator" class="org.apache.cloudstack.storage.allocator.ClusterScopeStoragePoolAllocator" />
<bean id="zoneWideStoragePoolAllocator" class="org.apache.cloudstack.storage.allocator.ZoneWideStoragePoolAllocator" />
diff --git a/engine/storage/pom.xml b/engine/storage/pom.xml
index 1c8ce4e9c0d..8da1259605a 100644
--- a/engine/storage/pom.xml
+++ b/engine/storage/pom.xml
@@ -16,7 +16,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/engine/storage/snapshot/pom.xml b/engine/storage/snapshot/pom.xml
index f074e251da7..2d8f54f059d 100644
--- a/engine/storage/snapshot/pom.xml
+++ b/engine/storage/snapshot/pom.xml
@@ -16,7 +16,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotBackupException.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotBackupException.java
new file mode 100644
index 00000000000..33b5aaa0673
--- /dev/null
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotBackupException.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cloudstack.storage.snapshot;
+
+import com.cloud.utils.SerialVersionUID;
+
+public class SnapshotBackupException extends Exception {
+ private static final long serialVersionUID = SerialVersionUID.SnapshotBackupException;
+
+ public SnapshotBackupException(String msg) {
+ super(msg);
+ }
+}
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
index b47f0cf251b..23e1650ffa0 100644
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
@@ -62,6 +62,7 @@
private SnapshotVO snapshot;
private DataStore store;
private Object payload;
+ private Boolean fullBackup;
@Inject
protected SnapshotDao snapshotDao;
@Inject
@@ -230,6 +231,11 @@ public String getName() {
return snapshot.getName();
}
+ @Override
+ public long getSnapshotId() {
+ return snapshot.getSnapshotId();
+ }
+
@Override
public Date getCreated() {
return snapshot.getCreated();
@@ -388,6 +394,16 @@ public Object getPayload() {
return payload;
}
+ @Override
+ public void setFullBackup(Boolean data) {
+ fullBackup = data;
+ }
+
+ @Override
+ public Boolean getFullBackup() {
+ return fullBackup;
+ }
+
@Override
public boolean delete() {
if (store != null) {
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java
index d13df9288a5..85c25f18839 100644
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java
@@ -24,7 +24,6 @@
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
-
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService;
@@ -44,16 +43,22 @@
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.framework.async.AsyncRpcContext;
+import org.apache.cloudstack.framework.jobs.AsyncJob;
import org.apache.cloudstack.storage.command.CommandResult;
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
+import com.cloud.storage.CreateSnapshotPayload;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.Snapshot;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.dao.SnapshotDao;
+import com.cloud.storage.dao.SnapshotDetailsDao;
import com.cloud.storage.template.TemplateConstants;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.db.TransactionCallbackNoReturn;
+import com.cloud.utils.db.TransactionStatus;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.fsm.NoTransitionException;
@@ -72,6 +77,8 @@
DataMotionService motionSrv;
@Inject
StorageCacheManager _cacheMgr;
+ @Inject
+ private SnapshotDetailsDao _snapshotDetailsDao;
static private class CreateSnapshotContext<T> extends AsyncRpcContext<T> {
final SnapshotInfo snapshot;
@@ -226,9 +233,9 @@ public SnapshotResult takeSnapshot(SnapshotInfo snap) {
// we are taking delta snapshot
private DataStore findSnapshotImageStore(SnapshotInfo snapshot) {
Boolean fullSnapshot = true;
- Object payload = snapshot.getPayload();
- if (payload != null) {
- fullSnapshot = (Boolean)payload;
+ Boolean snapshotFullBackup = snapshot.getFullBackup();
+ if (snapshotFullBackup != null) {
+ fullSnapshot = snapshotFullBackup;
}
if (fullSnapshot) {
return dataStoreMgr.getImageStore(snapshot.getDataCenterId());
@@ -300,19 +307,22 @@ protected Void copySnapshotAsyncCallback(AsyncCallbackDispatcher<SnapshotService
CopyCommandResult result = callback.getResult();
SnapshotInfo destSnapshot = context.destSnapshot;
SnapshotObject srcSnapshot = (SnapshotObject)context.srcSnapshot;
+ Object payload = srcSnapshot.getPayload();
+ CreateSnapshotPayload createSnapshotPayload = (CreateSnapshotPayload)payload;
AsyncCallFuture<SnapshotResult> future = context.future;
SnapshotResult snapResult = new SnapshotResult(destSnapshot, result.getAnswer());
if (result.isFailed()) {
try {
- destSnapshot.processEvent(Event.OperationFailed);
- //if backup snapshot failed, mark srcSnapshot in snapshot_store_ref as failed also
- srcSnapshot.processEvent(Event.DestroyRequested);
- srcSnapshot.processEvent(Event.OperationSuccessed);
-
- srcSnapshot.processEvent(Snapshot.Event.OperationFailed);
- _snapshotDao.remove(srcSnapshot.getId());
- } catch (NoTransitionException e) {
- s_logger.debug("Failed to update state: " + e.toString());
+ if (createSnapshotPayload.getAsyncBackup()) {
+ destSnapshot.processEvent(Event.OperationFailed);
+ throw new SnapshotBackupException("Failed in creating backup of snapshot with ID "+srcSnapshot.getId());
+ } else {
+ destSnapshot.processEvent(Event.OperationFailed);
+ //if backup snapshot failed, mark srcSnapshot in snapshot_store_ref as failed also
+ cleanupOnSnapshotBackupFailure(context.srcSnapshot);
+ }
+ } catch (SnapshotBackupException e) {
+ s_logger.debug("Failed to create backup: " + e.toString());
}
snapResult.setResult(result.getResult());
future.complete(snapResult);
@@ -547,4 +557,38 @@ protected Void syncSnapshotCallBack(AsyncCallbackDispatcher<SnapshotServiceImpl,
return null;
}
+
+ @Override
+ public void processEventOnSnapshotObject(SnapshotInfo snapshot, Snapshot.Event event) {
+ SnapshotObject object = (SnapshotObject)snapshot;
+ try {
+ object.processEvent(event);
+ } catch (NoTransitionException e) {
+ s_logger.debug("Unable to update the state " + e.toString());
+ }
+ }
+
+ @Override
+ public void cleanupOnSnapshotBackupFailure(SnapshotInfo snapshot) {
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ try {
+ SnapshotObject srcSnapshot = (SnapshotObject)snapshot;
+ srcSnapshot.processEvent(Event.DestroyRequested);
+ srcSnapshot.processEvent(Event.OperationSuccessed);
+
+ srcSnapshot.processEvent(Snapshot.Event.OperationFailed);
+
+ _snapshotDetailsDao.removeDetail(srcSnapshot.getId(), AsyncJob.Constants.MS_ID);
+ _snapshotDao.remove(srcSnapshot.getId());
+ } catch (NoTransitionException ex) {
+ s_logger.debug("Failed to create backup " + ex.toString());
+ throw new CloudRuntimeException("Failed to backup snapshot" + snapshot.getId());
+ }
+ }
+ });
+
+ }
+
}
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManagerImpl.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManagerImpl.java
index 9c6e3796887..413762b1fb6 100644
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManagerImpl.java
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManagerImpl.java
@@ -53,6 +53,7 @@ public SnapshotStateMachineManagerImpl() {
stateMachine.addTransition(Snapshot.State.Destroying, Event.OperationSucceeded, Snapshot.State.Destroyed);
stateMachine.addTransition(Snapshot.State.Destroying, Event.OperationFailed, State.BackedUp);
stateMachine.addTransition(Snapshot.State.Destroying, Event.DestroyRequested, Snapshot.State.Destroying);
+ stateMachine.addTransition(Snapshot.State.BackingUp, Event.BackupToSecondary, Snapshot.State.BackingUp);
stateMachine.registerListener(new SnapshotStateListener());
}
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/StorageSystemSnapshotStrategy.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/StorageSystemSnapshotStrategy.java
index 2742da6dc61..185cf567fa0 100644
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/StorageSystemSnapshotStrategy.java
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/StorageSystemSnapshotStrategy.java
@@ -214,7 +214,6 @@ public SnapshotInfo takeSnapshot(SnapshotInfo snapshotInfo) {
SnapshotResult result = null;
SnapshotInfo snapshotOnPrimary = null;
- SnapshotInfo backedUpSnapshot = null;
try {
volumeInfo.stateTransit(Volume.Event.SnapshotRequested);
@@ -250,23 +249,10 @@ public SnapshotInfo takeSnapshot(SnapshotInfo snapshotInfo) {
}
snapshotOnPrimary = result.getSnapshot();
- backedUpSnapshot = backupSnapshot(snapshotOnPrimary);
-
- updateLocationTypeInDb(backedUpSnapshot);
}
finally {
if (result != null && result.isSuccess()) {
volumeInfo.stateTransit(Volume.Event.OperationSucceeded);
-
- if (snapshotOnPrimary != null && snapshotInfo.getLocationType() == Snapshot.LocationType.SECONDARY) {
- // remove the snapshot on primary storage
- try {
- snapshotSvr.deleteSnapshot(snapshotOnPrimary);
- } catch (Exception e) {
- s_logger.warn("Failed to clean up snapshot on primary Id:" + snapshotOnPrimary.getId() + " "
- + e.getMessage());
- }
- }
} else {
volumeInfo.stateTransit(Volume.Event.OperationFailed);
}
@@ -274,7 +260,22 @@ public SnapshotInfo takeSnapshot(SnapshotInfo snapshotInfo) {
snapshotDao.releaseFromLockTable(snapshotInfo.getId());
- return backedUpSnapshot;
+ return snapshotOnPrimary;
+ }
+
+ @Override
+ public void postSnapshotCreation(SnapshotInfo snapshot) {
+ updateLocationTypeInDb(snapshot);
+
+ if (snapshot.getLocationType() == Snapshot.LocationType.SECONDARY) {
+ // remove the snapshot on primary storage
+ try {
+ snapshotSvr.deleteSnapshot(snapshot);
+ } catch (Exception e) {
+ s_logger.warn("Failed to clean up snapshot '" + snapshot.getId() + "' on primary storage: " + e.getMessage());
+ }
+ }
+
}
private void updateLocationTypeInDb(SnapshotInfo snapshotInfo) {
@@ -604,4 +605,5 @@ public StrategyPriority canHandle(Snapshot snapshot, SnapshotOperation op) {
return StrategyPriority.CANT_HANDLE;
}
+
}
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java
index 165d3564b75..a673a462375 100644
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java
@@ -33,13 +33,15 @@
import org.apache.cloudstack.engine.subsystem.api.storage.StrategyPriority;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.framework.jobs.AsyncJob;
+import org.apache.cloudstack.framework.jobs.dao.SyncQueueItemDao;
import org.apache.cloudstack.storage.command.CreateObjectAnswer;
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
import org.apache.cloudstack.storage.datastore.PrimaryDataStoreImpl;
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
+import org.apache.cloudstack.utils.identity.ManagementServerNode;
-import com.cloud.configuration.Config;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
@@ -52,7 +54,11 @@
import com.cloud.storage.Volume;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.SnapshotDao;
+import com.cloud.storage.dao.SnapshotDetailsDao;
import com.cloud.storage.dao.VolumeDao;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.db.TransactionCallbackNoReturn;
+import com.cloud.utils.db.TransactionStatus;
import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.StoragePoolType;
@@ -81,6 +87,10 @@
SnapshotDataFactory snapshotDataFactory;
@Inject
private SnapshotDao _snapshotDao;
+ @Inject
+ private SnapshotDetailsDao _snapshotDetailsDao;
+ @Inject
+ private SyncQueueItemDao _syncQueueItemDao;
@Override
public SnapshotInfo backupSnapshot(SnapshotInfo snapshot) {
@@ -159,7 +169,7 @@ public SnapshotInfo backupSnapshot(SnapshotInfo snapshot) {
}
}
- snapshot.addPayload(fullBackup);
+ snapshot.setFullBackup(fullBackup);
return snapshotSvr.backupSnapshot(snapshot);
}
@@ -356,9 +366,11 @@ public boolean revertSnapshot(SnapshotInfo snapshot) {
@Override
@DB
public SnapshotInfo takeSnapshot(SnapshotInfo snapshot) {
+ SnapshotInfo snapshotOnPrimary = null;
Object payload = snapshot.getPayload();
+ CreateSnapshotPayload createSnapshotPayload = null;
if (payload != null) {
- CreateSnapshotPayload createSnapshotPayload = (CreateSnapshotPayload)payload;
+ createSnapshotPayload = (CreateSnapshotPayload)payload;
if (createSnapshotPayload.getQuiescevm()) {
throw new InvalidParameterValueException("can't handle quiescevm equal true for volume snapshot");
}
@@ -386,58 +398,53 @@ public SnapshotInfo takeSnapshot(SnapshotInfo snapshot) {
volumeInfo.stateTransit(Volume.Event.OperationFailed);
}
}
+ snapshotOnPrimary = result.getSnapshot();
+ snapshotOnPrimary.addPayload(snapshot.getPayload());
- snapshot = result.getSnapshot();
- DataStore primaryStore = snapshot.getDataStore();
- boolean backupFlag = Boolean.parseBoolean(configDao.getValue(Config.BackupSnapshotAfterTakingSnapshot.toString()));
-
- SnapshotInfo backupedSnapshot;
- if(backupFlag) {
- backupedSnapshot = backupSnapshot(snapshot);
- } else {
- // Fake it to get the transitions to fire in the proper order
- s_logger.debug("skipping backup of snapshot due to configuration "+Config.BackupSnapshotAfterTakingSnapshot.toString());
-
- SnapshotObject snapObj = (SnapshotObject)snapshot;
- try {
- snapObj.processEvent(Snapshot.Event.OperationNotPerformed);
- } catch (NoTransitionException e) {
- s_logger.debug("Failed to change state: " + snapshot.getId() + ": " + e.toString());
- throw new CloudRuntimeException(e.toString());
- }
- backupedSnapshot = snapshot;
+ /*The Management Server ID is stored in snapshot_details table with the snapshot id and (name, value): (MS_ID, <ms_id>), to know which snapshots have not been completed in case of some failure situation like
+ * Mgmt server down etc. and by fetching the entries on restart the cleaning up of failed snapshots is done*/
+ _snapshotDetailsDao.addDetail(((SnapshotObject)snapshotOnPrimary).getId(), AsyncJob.Constants.MS_ID, Long.toString(ManagementServerNode.getManagementServerId()), false);
+ return snapshotOnPrimary;
+ } finally {
+ if (snapshotVO != null) {
+ snapshotDao.releaseFromLockTable(snapshot.getId());
}
+ }
+ }
- try {
- SnapshotInfo parent = snapshot.getParent();
- if (backupedSnapshot != null && parent != null && primaryStore instanceof PrimaryDataStoreImpl) {
- if (((PrimaryDataStoreImpl)primaryStore).getPoolType() != StoragePoolType.RBD) {
- Long parentSnapshotId = parent.getId();
- while (parentSnapshotId != null && parentSnapshotId != 0L) {
- SnapshotDataStoreVO snapshotDataStoreVO = snapshotStoreDao.findByStoreSnapshot(primaryStore.getRole(), primaryStore.getId(), parentSnapshotId);
- if (snapshotDataStoreVO != null) {
- parentSnapshotId = snapshotDataStoreVO.getParentSnapshotId();
- snapshotStoreDao.remove(snapshotDataStoreVO.getId());
- } else {
- parentSnapshotId = null;
+ @Override
+ public void postSnapshotCreation(SnapshotInfo snapshotOnPrimary) {
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ _snapshotDetailsDao.removeDetail(((SnapshotObject)snapshotOnPrimary).getId(), AsyncJob.Constants.MS_ID);
+ DataStore primaryStore = snapshotOnPrimary.getDataStore();
+ try {
+ SnapshotInfo parent = snapshotOnPrimary.getParent();
+ if (parent != null && primaryStore instanceof PrimaryDataStoreImpl) {
+ if (((PrimaryDataStoreImpl)primaryStore).getPoolType() != StoragePoolType.RBD) {
+ Long parentSnapshotId = parent.getId();
+ while (parentSnapshotId != null && parentSnapshotId != 0L) {
+ SnapshotDataStoreVO snapshotDataStoreVO = snapshotStoreDao.findByStoreSnapshot(primaryStore.getRole(), primaryStore.getId(), parentSnapshotId);
+ if (snapshotDataStoreVO != null) {
+ parentSnapshotId = snapshotDataStoreVO.getParentSnapshotId();
+ snapshotStoreDao.remove(snapshotDataStoreVO.getId());
+ } else {
+ parentSnapshotId = null;
+ }
}
}
+ SnapshotDataStoreVO snapshotDataStoreVO = snapshotStoreDao.findByStoreSnapshot(primaryStore.getRole(), primaryStore.getId(), snapshotOnPrimary.getId());
+ if (snapshotDataStoreVO != null) {
+ snapshotDataStoreVO.setParentSnapshotId(0L);
+ snapshotStoreDao.update(snapshotDataStoreVO.getId(), snapshotDataStoreVO);
+ }
}
- SnapshotDataStoreVO snapshotDataStoreVO = snapshotStoreDao.findByStoreSnapshot(primaryStore.getRole(), primaryStore.getId(), snapshot.getId());
- if (snapshotDataStoreVO != null) {
- snapshotDataStoreVO.setParentSnapshotId(0L);
- snapshotStoreDao.update(snapshotDataStoreVO.getId(), snapshotDataStoreVO);
- }
+ } catch (Exception e) {
+ s_logger.debug("Failed to clean up snapshots on primary storage", e);
}
- } catch (Exception e) {
- s_logger.debug("Failed to clean up snapshots on primary storage", e);
}
- return backupedSnapshot;
- } finally {
- if (snapshotVO != null) {
- snapshotDao.releaseFromLockTable(snapshot.getId());
- }
- }
+ });
}
@Override
@@ -455,4 +462,5 @@ public StrategyPriority canHandle(Snapshot snapshot, SnapshotOperation op) {
return StrategyPriority.DEFAULT;
}
+
}
diff --git a/engine/storage/snapshot/test/resources/db.properties b/engine/storage/snapshot/test/resources/db.properties
index e8e94121fe1..eabc445c208 100644
--- a/engine/storage/snapshot/test/resources/db.properties
+++ b/engine/storage/snapshot/test/resources/db.properties
@@ -17,7 +17,7 @@
# management server clustering parameters, change cluster.node.IP to the machine IP address
-# in which the management server(Tomcat) is running
+# in which the management server is running
cluster.node.IP=127.0.0.1
cluster.servlet.port=9090
diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java
index 9ffeae06e0b..c3e48b9b2f3 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java
@@ -33,6 +33,12 @@
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
+import com.cloud.storage.SnapshotVO;
+import com.cloud.storage.dao.SnapshotDao;
+import javax.inject.Inject;
+import com.cloud.hypervisor.Hypervisor;
+import java.util.ArrayList;
+import com.cloud.utils.db.Filter;
import javax.naming.ConfigurationException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -54,9 +60,14 @@
private SearchBuilder<SnapshotDataStoreVO> volumeIdSearch;
private SearchBuilder<SnapshotDataStoreVO> volumeSearch;
private SearchBuilder<SnapshotDataStoreVO> stateSearch;
+ private SearchBuilder<SnapshotDataStoreVO> parentSnapshotSearch;
+ private SearchBuilder<SnapshotVO> snapshotVOSearch;
+
+ public static ArrayList<Hypervisor.HypervisorType> hypervisorsSupportingSnapshotsChaining = new ArrayList<Hypervisor.HypervisorType>();
+
+ @Inject
+ private SnapshotDao _snapshotDao;
- private final String parentSearch = "select store_id, store_role, snapshot_id from cloud.snapshot_store_ref where store_id = ? "
- + " and store_role = ? and volume_id = ? and state = 'Ready'" + " order by created DESC " + " limit 1";
private final String findLatestSnapshot = "select store_id, store_role, snapshot_id from cloud.snapshot_store_ref where " +
" store_role = ? and volume_id = ? and state = 'Ready'" +
" order by created DESC " +
@@ -128,6 +139,17 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
stateSearch.and("state", stateSearch.entity().getState(), SearchCriteria.Op.IN);
stateSearch.done();
+ parentSnapshotSearch = createSearchBuilder();
+ parentSnapshotSearch.and("volume_id", parentSnapshotSearch.entity().getVolumeId(), SearchCriteria.Op.EQ);
+ parentSnapshotSearch.and("store_id", parentSnapshotSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ);
+ parentSnapshotSearch.and("store_role", parentSnapshotSearch.entity().getRole(), SearchCriteria.Op.EQ);
+ parentSnapshotSearch.and("state", parentSnapshotSearch.entity().getState(), SearchCriteria.Op.EQ);
+ parentSnapshotSearch.done();
+
+ snapshotVOSearch = _snapshotDao.createSearchBuilder();
+ snapshotVOSearch.and("volume_id", snapshotVOSearch.entity().getVolumeId(), SearchCriteria.Op.EQ);
+ snapshotVOSearch.done();
+
return true;
}
@@ -272,22 +294,17 @@ public SnapshotDataStoreVO findOldestSnapshotForVolume(Long volumeId, DataStoreR
@Override
@DB
public SnapshotDataStoreVO findParent(DataStoreRole role, Long storeId, Long volumeId) {
- TransactionLegacy txn = TransactionLegacy.currentTxn();
- try (
- PreparedStatement pstmt = txn.prepareStatement(parentSearch);
- ){
- pstmt.setLong(1, storeId);
- pstmt.setString(2, role.toString());
- pstmt.setLong(3, volumeId);
- try (ResultSet rs = pstmt.executeQuery();) {
- while (rs.next()) {
- long sid = rs.getLong(1);
- long snid = rs.getLong(3);
- return findByStoreSnapshot(role, sid, snid);
- }
+ if(isSnapshotChainingRequired(volumeId)) {
+ SearchCriteria<SnapshotDataStoreVO> sc = parentSnapshotSearch.create();
+ sc.setParameters("volume_id", volumeId);
+ sc.setParameters("store_role", role.toString());
+ sc.setParameters("state", ObjectInDataStoreStateMachine.State.Ready.name());
+ sc.setParameters("store_id", storeId);
+
+ List<SnapshotDataStoreVO> snapshotList = listBy(sc, new Filter(SnapshotDataStoreVO.class, "created", false, null, null));
+ if (snapshotList != null && snapshotList.size() != 0) {
+ return snapshotList.get(0);
}
- } catch (SQLException e) {
- s_logger.debug("Failed to find parent snapshot: " + e.toString());
}
return null;
}
@@ -419,4 +436,21 @@ public void updateVolumeIds(long oldVolId, long newVolId) {
sc.setParameters("state", (Object[])states);
return listBy(sc, null);
}
+
+ private boolean isSnapshotChainingRequired(long volumeId) {
+
+ hypervisorsSupportingSnapshotsChaining.add(Hypervisor.HypervisorType.XenServer);
+
+ SearchCriteria<SnapshotVO> sc = snapshotVOSearch.create();
+ sc.setParameters("volume_id", volumeId);
+
+ SnapshotVO volSnapshot = _snapshotDao.findOneBy(sc);
+
+ if (volSnapshot != null && hypervisorsSupportingSnapshotsChaining.contains(volSnapshot.getHypervisorType())) {
+ return true;
+ }
+
+ return false;
+ }
+
}
diff --git a/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java b/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java
index 3cea3eae9b9..24e77a8a544 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java
@@ -94,6 +94,12 @@ public String getName() {
return null;
}
+ @Override
+ public long getSnapshotId() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
@Override
public Date getCreated() {
// TODO Auto-generated method stub
diff --git a/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreDaoImpl.java
deleted file mode 100644
index 75838b02581..00000000000
--- a/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreDaoImpl.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.cloudstack.storage.volume.db;
-
-import java.util.Date;
-
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
-
-import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
-import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
-import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State;
-
-import com.cloud.utils.db.GenericDaoBase;
-import com.cloud.utils.db.QueryBuilder;
-import com.cloud.utils.db.SearchBuilder;
-import com.cloud.utils.db.SearchCriteria;
-import com.cloud.utils.db.SearchCriteria.Op;
-import com.cloud.utils.db.UpdateBuilder;
-
-@Component
-public class TemplatePrimaryDataStoreDaoImpl extends GenericDaoBase<TemplatePrimaryDataStoreVO, Long> implements TemplatePrimaryDataStoreDao {
- private static final Logger s_logger = Logger.getLogger(TemplatePrimaryDataStoreDaoImpl.class);
- protected final SearchBuilder<TemplatePrimaryDataStoreVO> updateSearchBuilder;
-
- public TemplatePrimaryDataStoreDaoImpl() {
- updateSearchBuilder = createSearchBuilder();
- updateSearchBuilder.and("id", updateSearchBuilder.entity().getId(), Op.EQ);
- updateSearchBuilder.and("state", updateSearchBuilder.entity().getState(), Op.EQ);
- updateSearchBuilder.and("updatedCount", updateSearchBuilder.entity().getUpdatedCount(), Op.EQ);
- updateSearchBuilder.done();
- }
-
- @Override
- public TemplatePrimaryDataStoreVO findByTemplateIdAndPoolId(long templateId, long poolId) {
- QueryBuilder<TemplatePrimaryDataStoreVO> sc = QueryBuilder.create(TemplatePrimaryDataStoreVO.class);
- sc.and(sc.entity().getTemplateId(), Op.EQ, templateId);
- sc.and(sc.entity().getPoolId(), Op.EQ, poolId);
- return sc.find();
- }
-
- @Override
- public TemplatePrimaryDataStoreVO findByTemplateIdAndPoolIdAndReady(long templateId, long poolId) {
- QueryBuilder<TemplatePrimaryDataStoreVO> sc = QueryBuilder.create(TemplatePrimaryDataStoreVO.class);
- sc.and(sc.entity().getTemplateId(), Op.EQ, templateId);
- sc.and(sc.entity().getPoolId(), Op.EQ, poolId);
- sc.and(sc.entity().getState(), Op.EQ, ObjectInDataStoreStateMachine.State.Ready);
- return sc.find();
- }
-
- @Override
- public boolean updateState(State currentState, Event event, State nextState, TemplatePrimaryDataStoreVO vo, Object data) {
- Long oldUpdated = vo.getUpdatedCount();
- Date oldUpdatedTime = vo.getLastUpdated();
-
- SearchCriteria<TemplatePrimaryDataStoreVO> sc = updateSearchBuilder.create();
- sc.setParameters("id", vo.getId());
- sc.setParameters("state", currentState);
- sc.setParameters("updatedCount", vo.getUpdatedCount());
-
- vo.incrUpdatedCount();
-
- UpdateBuilder builder = getUpdateBuilder(vo);
- builder.set(vo, "state", nextState);
- builder.set(vo, "lastUpdated", new Date());
-
- int rows = update(vo, sc);
- if (rows == 0 && s_logger.isDebugEnabled()) {
- TemplatePrimaryDataStoreVO template = findByIdIncludingRemoved(vo.getId());
- if (template != null) {
- StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString());
- str.append(": DB Data={id=")
- .append(template.getId())
- .append("; state=")
- .append(template.getState())
- .append("; updatecount=")
- .append(template.getUpdatedCount())
- .append(";updatedTime=")
- .append(template.getLastUpdated());
- str.append(": New Data={id=")
- .append(vo.getId())
- .append("; state=")
- .append(nextState)
- .append("; event=")
- .append(event)
- .append("; updatecount=")
- .append(vo.getUpdatedCount())
- .append("; updatedTime=")
- .append(vo.getLastUpdated());
- str.append(": stale Data={id=")
- .append(vo.getId())
- .append("; state=")
- .append(currentState)
- .append("; event=")
- .append(event)
- .append("; updatecount=")
- .append(oldUpdated)
- .append("; updatedTime=")
- .append(oldUpdatedTime);
- } else {
- s_logger.debug("Unable to update template: id=" + vo.getId() + ", as there is no such template exists in the database anymore");
- }
- }
- return rows > 0;
- }
-
-}
diff --git a/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreVO.java b/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreVO.java
deleted file mode 100644
index 9635729442b..00000000000
--- a/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreVO.java
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.cloudstack.storage.volume.db;
-
-import java.util.Date;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.Table;
-import javax.persistence.Temporal;
-import javax.persistence.TemporalType;
-
-import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
-
-import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
-import com.cloud.utils.db.GenericDaoBase;
-import com.cloud.utils.fsm.StateObject;
-
-@Entity
-@Table(name = "template_spool_ref")
-public class TemplatePrimaryDataStoreVO implements StateObject<ObjectInDataStoreStateMachine.State> {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- long id;
-
- @Column(name = "pool_id")
- private long poolId;
-
- @Column(name = "template_id")
- long templateId;
-
- @Column(name = GenericDaoBase.CREATED_COLUMN)
- Date created = null;
-
- @Column(name = "last_updated")
- @Temporal(value = TemporalType.TIMESTAMP)
- Date lastUpdated = null;
-
- @Column(name = "download_pct")
- int downloadPercent;
-
- @Column(name = "download_state")
- @Enumerated(EnumType.STRING)
- Status downloadState;
-
- @Column(name = "local_path")
- String localDownloadPath;
-
- @Column(name = "error_str")
- String errorString;
-
- @Column(name = "job_id")
- String jobId;
-
- @Column(name = "install_path")
- String installPath;
-
- @Column(name = "template_size")
- long templateSize;
-
- @Column(name = "marked_for_gc")
- boolean markedForGC;
-
- @Column(name = "state")
- @Enumerated(EnumType.STRING)
- ObjectInDataStoreStateMachine.State state;
-
- @Column(name = "update_count", updatable = true, nullable = false)
- protected long updatedCount;
-
- public long getUpdatedCount() {
- return this.updatedCount;
- }
-
- public void incrUpdatedCount() {
- this.updatedCount++;
- }
-
- public void decrUpdatedCount() {
- this.updatedCount--;
- }
-
- public String getInstallPath() {
- return installPath;
- }
-
- public long getTemplateSize() {
- return templateSize;
- }
-
- public long getPoolId() {
- return poolId;
- }
-
- public void setpoolId(long poolId) {
- this.poolId = poolId;
- }
-
- public long getTemplateId() {
- return templateId;
- }
-
- public void setTemplateId(long templateId) {
- this.templateId = templateId;
- }
-
- public int getDownloadPercent() {
- return downloadPercent;
- }
-
- public void setDownloadPercent(int downloadPercent) {
- this.downloadPercent = downloadPercent;
- }
-
- public void setDownloadState(Status downloadState) {
- this.downloadState = downloadState;
- }
-
- public long getId() {
- return id;
- }
-
- public Date getCreated() {
- return created;
- }
-
- public Date getLastUpdated() {
- return lastUpdated;
- }
-
- public void setLastUpdated(Date date) {
- lastUpdated = date;
- }
-
- public void setInstallPath(String installPath) {
- this.installPath = installPath;
- }
-
- public Status getDownloadState() {
- return downloadState;
- }
-
- public TemplatePrimaryDataStoreVO(long poolId, long templateId) {
- super();
- this.poolId = poolId;
- this.templateId = templateId;
- this.downloadState = Status.NOT_DOWNLOADED;
- this.state = ObjectInDataStoreStateMachine.State.Allocated;
- this.markedForGC = false;
- }
-
- public TemplatePrimaryDataStoreVO(long poolId, long templateId, Date lastUpdated, int downloadPercent, Status downloadState, String localDownloadPath,
- String errorString, String jobId, String installPath, long templateSize) {
- super();
- this.poolId = poolId;
- this.templateId = templateId;
- this.lastUpdated = lastUpdated;
- this.downloadPercent = downloadPercent;
- this.downloadState = downloadState;
- this.localDownloadPath = localDownloadPath;
- this.errorString = errorString;
- this.jobId = jobId;
- this.installPath = installPath;
- this.templateSize = templateSize;
- }
-
- protected TemplatePrimaryDataStoreVO() {
-
- }
-
- public void setLocalDownloadPath(String localPath) {
- this.localDownloadPath = localPath;
- }
-
- public String getLocalDownloadPath() {
- return localDownloadPath;
- }
-
- public void setErrorString(String errorString) {
- this.errorString = errorString;
- }
-
- public String getErrorString() {
- return errorString;
- }
-
- public void setJobId(String jobId) {
- this.jobId = jobId;
- }
-
- public String getJobId() {
- return jobId;
- }
-
- public void setTemplateSize(long templateSize) {
- this.templateSize = templateSize;
- }
-
- public boolean getMarkedForGC() {
- return markedForGC;
- }
-
- public void setMarkedForGC(boolean markedForGC) {
- this.markedForGC = markedForGC;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof TemplatePrimaryDataStoreVO) {
- TemplatePrimaryDataStoreVO other = (TemplatePrimaryDataStoreVO)obj;
- return (this.templateId == other.getTemplateId() && this.poolId == other.getPoolId());
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- Long tid = new Long(templateId);
- Long hid = new Long(poolId);
- return tid.hashCode() + hid.hashCode();
- }
-
- @Override
- public String toString() {
- return new StringBuilder("TmplPool[").append(id)
- .append("-")
- .append(templateId)
- .append("-")
- .append("poolId")
- .append("-")
- .append(installPath)
- .append("]")
- .toString();
- }
-
- @Override
- public ObjectInDataStoreStateMachine.State getState() {
- return this.state;
- }
-
-}
\ No newline at end of file
diff --git a/engine/storage/volume/pom.xml b/engine/storage/volume/pom.xml
index 0b5b6bbb5b9..bc6eaf8bf60 100644
--- a/engine/storage/volume/pom.xml
+++ b/engine/storage/volume/pom.xml
@@ -16,7 +16,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/framework/ca/pom.xml b/framework/ca/pom.xml
new file mode 100644
index 00000000000..9412649b3b9
--- /dev/null
+++ b/framework/ca/pom.xml
@@ -0,0 +1,29 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>cloud-framework-ca</artifactId>
+ <name>Apache CloudStack Framework - Certificate Authority</name>
+ <parent>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloudstack-framework</artifactId>
+ <version>4.11.0.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+</project>
diff --git a/framework/ca/src/org/apache/cloudstack/framework/ca/CAProvider.java b/framework/ca/src/org/apache/cloudstack/framework/ca/CAProvider.java
new file mode 100644
index 00000000000..388cae7e007
--- /dev/null
+++ b/framework/ca/src/org/apache/cloudstack/framework/ca/CAProvider.java
@@ -0,0 +1,107 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.framework.ca;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.cert.X509Certificate;
+import java.util.List;
+import java.util.Map;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+
+public interface CAProvider {
+
+ /**
+ * Method returns capability of the plugin to participate in certificate issuance, revocation and provisioning
+ * @return returns true when CA provider can do certificate lifecycle tasks
+ */
+ boolean canProvisionCertificates();
+
+ /**
+ * Returns root CA certificate
+ * @return returns concatenated root CA certificate string
+ */
+ List<X509Certificate> getCaCertificate();
+
+ /**
+ * Issues certificate with provided options
+ * @param domainNames
+ * @param ipAddresses
+ * @param validityDays
+ * @return returns issued certificate
+ */
+ Certificate issueCertificate(final List<String> domainNames, final List<String> ipAddresses, final int validityDays);
+
+ /**
+ * Issues certificate using given CSR and other options
+ * @param csr
+ * @param domainNames
+ * @param ipAddresses
+ * @param validityDays
+ * @return returns issued certificate using provided CSR and other options
+ */
+ Certificate issueCertificate(final String csr, final List<String> domainNames, final List<String> ipAddresses, final int validityDays);
+
+ /**
+ * Revokes certificate using certificate serial and CN
+ * @param certSerial
+ * @param certCn
+ * @return returns true on success
+ */
+ boolean revokeCertificate(final BigInteger certSerial, final String certCn);
+
+ /**
+ * This method can add/inject custom TrustManagers for client connection validations.
+ * @param sslContext The SSL context used while accepting a client connection
+ * @param remoteAddress
+ * @param certMap
+ * @return returns created SSL engine instance
+ * @throws GeneralSecurityException
+ * @throws IOException
+ */
+ SSLEngine createSSLEngine(final SSLContext sslContext, final String remoteAddress, final Map<String, X509Certificate> certMap) throws GeneralSecurityException, IOException;
+
+ /**
+ * Returns the management server keystore used to connect to peers
+ * @return returns KeyStore instance
+ */
+ KeyStore getManagementKeyStore() throws KeyStoreException;
+
+ /**
+ * Returns the keystore passphrase to use
+ * @return returns char[] passphrase
+ */
+ char[] getKeyStorePassphrase();
+
+ /**
+ * Returns the unique name of the provider
+ * @return returns provider name
+ */
+ String getProviderName();
+
+ /**
+ * Returns description about the CA provider plugin
+ * @return returns description
+ */
+ String getDescription();
+}
diff --git a/framework/ca/src/org/apache/cloudstack/framework/ca/CAService.java b/framework/ca/src/org/apache/cloudstack/framework/ca/CAService.java
new file mode 100644
index 00000000000..facf13a5cb6
--- /dev/null
+++ b/framework/ca/src/org/apache/cloudstack/framework/ca/CAService.java
@@ -0,0 +1,50 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.framework.ca;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+
+public interface CAService {
+ /**
+ * Returns a SSLEngine to be used for handling client connections
+ * @param context
+ * @param remoteAddress
+ * @return
+ * @throws GeneralSecurityException
+ * @throws IOException
+ */
+ SSLEngine createSSLEngine(final SSLContext context, final String remoteAddress) throws GeneralSecurityException, IOException;
+
+ /**
+ * Returns the management server keystore used to connect to peers
+ * @return returns KeyStore instance
+ */
+ KeyStore getManagementKeyStore() throws KeyStoreException;
+
+ /**
+ * Returns the keystore passphrase to use
+ * @return returns char[] passphrase
+ */
+ char[] getKeyStorePassphrase();
+}
diff --git a/framework/ca/src/org/apache/cloudstack/framework/ca/Certificate.java b/framework/ca/src/org/apache/cloudstack/framework/ca/Certificate.java
new file mode 100644
index 00000000000..b3a230d5a99
--- /dev/null
+++ b/framework/ca/src/org/apache/cloudstack/framework/ca/Certificate.java
@@ -0,0 +1,46 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.framework.ca;
+
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+public class Certificate {
+ private X509Certificate clientCertificate;
+ private PrivateKey privateKey;
+ private List<X509Certificate> caCertificates;
+
+ public Certificate(final X509Certificate clientCertificate, final PrivateKey privateKey, final List<X509Certificate> caCertificates) {
+ this.clientCertificate = clientCertificate;
+ this.privateKey = privateKey;
+ this.caCertificates = caCertificates;
+ }
+
+ public X509Certificate getClientCertificate() {
+ return clientCertificate;
+ }
+
+ public PrivateKey getPrivateKey() {
+ return privateKey;
+ }
+
+ public List<X509Certificate> getCaCertificates() {
+ return caCertificates;
+ }
+}
diff --git a/framework/cluster/pom.xml b/framework/cluster/pom.xml
index fadffc5520a..42b8042df22 100644
--- a/framework/cluster/pom.xml
+++ b/framework/cluster/pom.xml
@@ -15,7 +15,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-framework</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/framework/config/pom.xml b/framework/config/pom.xml
index 27a36ebe9b7..105ab9501ca 100644
--- a/framework/config/pom.xml
+++ b/framework/config/pom.xml
@@ -15,7 +15,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-framework</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/framework/config/src/org/apache/cloudstack/framework/config/ConfigKey.java b/framework/config/src/org/apache/cloudstack/framework/config/ConfigKey.java
index 4a41306bf55..fb2a57b71f6 100644
--- a/framework/config/src/org/apache/cloudstack/framework/config/ConfigKey.java
+++ b/framework/config/src/org/apache/cloudstack/framework/config/ConfigKey.java
@@ -140,7 +140,8 @@ public boolean isSameKeyAs(Object obj) {
public T value() {
if (_value == null || isDynamic()) {
ConfigurationVO vo = s_depot != null ? s_depot.global().findById(key()) : null;
- _value = valueOf((vo != null && vo.getValue() != null) ? vo.getValue() : defaultValue());
+ final String value = (vo != null && vo.getValue() != null) ? vo.getValue() : defaultValue();
+ _value = ((value == null) ? (T)defaultValue() : valueOf(value));
}
return _value;
diff --git a/framework/db/pom.xml b/framework/db/pom.xml
index e2bd79ace15..f83eca413f5 100644
--- a/framework/db/pom.xml
+++ b/framework/db/pom.xml
@@ -15,7 +15,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-framework</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/framework/events/pom.xml b/framework/events/pom.xml
index 0dc4ca68287..8f303038705 100644
--- a/framework/events/pom.xml
+++ b/framework/events/pom.xml
@@ -15,7 +15,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-framework</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/framework/ipc/pom.xml b/framework/ipc/pom.xml
index 43fdd0f25a5..39976f97e0e 100644
--- a/framework/ipc/pom.xml
+++ b/framework/ipc/pom.xml
@@ -16,7 +16,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-framework</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/framework/jobs/pom.xml b/framework/jobs/pom.xml
index 0811137f32c..d75f89d145d 100644
--- a/framework/jobs/pom.xml
+++ b/framework/jobs/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-framework</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJob.java b/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJob.java
index 0ad49e1e7bf..b8200bf8221 100644
--- a/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJob.java
+++ b/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJob.java
@@ -41,6 +41,8 @@
// is defined
public static final int SIGNAL_MASK_WAKEUP = 1;
+ public static final String MS_ID = "MS_ID";
+
public static final String SYNC_LOCK_NAME = "SyncLock";
}
diff --git a/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java b/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java
index 9b6aa7ccc61..7f2e1567d7a 100644
--- a/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java
+++ b/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java
@@ -39,6 +39,9 @@
import org.apache.log4j.NDC;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
+import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
+import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.framework.jobs.AsyncJob;
@@ -60,6 +63,11 @@
import com.cloud.cluster.ClusterManagerListener;
import com.cloud.cluster.ManagementServerHost;
+import com.cloud.storage.DataStoreRole;
+import com.cloud.storage.Snapshot;
+import com.cloud.storage.dao.SnapshotDao;
+import com.cloud.storage.dao.SnapshotDetailsDao;
+import com.cloud.storage.dao.SnapshotDetailsVO;
import com.cloud.utils.DateUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.Predicate;
@@ -84,6 +92,7 @@
import com.cloud.utils.exception.ExceptionUtil;
import com.cloud.utils.mgmt.JmxUtil;
import com.cloud.vm.dao.VMInstanceDao;
+import com.cloud.storage.dao.VolumeDao;
public class AsyncJobManagerImpl extends ManagerBase implements AsyncJobManager, ClusterManagerListener, Configurable {
// Advanced
@@ -123,6 +132,16 @@
private VMInstanceDao _vmInstanceDao;
@Inject
private VolumeDetailsDao _volumeDetailsDao;
+ @Inject
+ private VolumeDao _volsDao;
+ @Inject
+ private SnapshotDao _snapshotDao;
+ @Inject
+ private SnapshotService snapshotSrv;
+ @Inject
+ private SnapshotDataFactory snapshotFactory;
+ @Inject
+ private SnapshotDetailsDao _snapshotDetailsDao;
private volatile long _executionRunNumber = 1;
@@ -1020,11 +1039,18 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
try {
_volumeDetailsDao.removeDetail(job.getInstanceId(), "SNAPSHOT_ID");
+ _volsDao.remove(job.getInstanceId());
} catch (Exception e) {
s_logger.error("Unexpected exception while removing concurrent request meta data :" + e.getLocalizedMessage());
}
}
}
+ List<SnapshotDetailsVO> snapshotList = _snapshotDetailsDao.findDetails(AsyncJob.Constants.MS_ID, Long.toString(msid), false);
+ for (SnapshotDetailsVO snapshotDetailsVO : snapshotList) {
+ SnapshotInfo snapshot = snapshotFactory.getSnapshot(snapshotDetailsVO.getResourceId(), DataStoreRole.Primary);
+ snapshotSrv.processEventOnSnapshotObject(snapshot, Snapshot.Event.OperationFailed);
+ _snapshotDetailsDao.removeDetail(snapshotDetailsVO.getResourceId(), AsyncJob.Constants.MS_ID);
+ }
}
});
} catch (Throwable e) {
diff --git a/framework/managed-context/pom.xml b/framework/managed-context/pom.xml
index 919e22b1927..9140753a85b 100644
--- a/framework/managed-context/pom.xml
+++ b/framework/managed-context/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-maven-standard</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../maven-standard/pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/framework/pom.xml b/framework/pom.xml
index 5ee2be019f3..5bfb1d094fb 100644
--- a/framework/pom.xml
+++ b/framework/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
</parent>
<build>
<defaultGoal>install</defaultGoal>
@@ -44,6 +44,7 @@
</build>
<modules>
<module>ipc</module>
+ <module>ca</module>
<module>rest</module>
<module>events</module>
<module>jobs</module>
diff --git a/framework/quota/pom.xml b/framework/quota/pom.xml
index 372b98797c8..5649d637024 100644
--- a/framework/quota/pom.xml
+++ b/framework/quota/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-framework</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/framework/quota/src/org/apache/cloudstack/quota/constant/QuotaTypes.java b/framework/quota/src/org/apache/cloudstack/quota/constant/QuotaTypes.java
index 36910f47741..6e1432d848d 100644
--- a/framework/quota/src/org/apache/cloudstack/quota/constant/QuotaTypes.java
+++ b/framework/quota/src/org/apache/cloudstack/quota/constant/QuotaTypes.java
@@ -57,7 +57,7 @@
quotaTypeList.put(VM_SNAPSHOT, new QuotaTypes(VM_SNAPSHOT, "VM_SNAPSHOT", "GB-Month", "VM Snapshot storage usage"));
quotaTypeList.put(CPU_CLOCK_RATE, new QuotaTypes(CPU_CLOCK_RATE, "CPU_CLOCK_RATE", "Compute-Month", "Quota tariff for using 1 CPU of clock rate 100MHz"));
quotaTypeList.put(CPU_NUMBER, new QuotaTypes(CPU_NUMBER, "CPU_NUMBER", "Compute-Month", "Quota tariff for running VM that has 1vCPU"));
- quotaTypeList.put(MEMORY, new QuotaTypes(MEMORY, "MEMORY", "Compute-Month", "Quota tariff for using 1MB or RAM for 1 hour"));
+ quotaTypeList.put(MEMORY, new QuotaTypes(MEMORY, "MEMORY", "Compute-Month", "Quota tariff for using 1MB of RAM"));
quotaTypeMap = Collections.unmodifiableMap(quotaTypeList);
}
diff --git a/framework/rest/pom.xml b/framework/rest/pom.xml
index e50bfe24d8d..4c5923a8701 100644
--- a/framework/rest/pom.xml
+++ b/framework/rest/pom.xml
@@ -22,7 +22,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-framework</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>cloud-framework-rest</artifactId>
diff --git a/framework/security/pom.xml b/framework/security/pom.xml
index fe6bb4b8dc4..7886edfc216 100644
--- a/framework/security/pom.xml
+++ b/framework/security/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-framework</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/framework/spring/lifecycle/pom.xml b/framework/spring/lifecycle/pom.xml
index 45ba4de56d1..ee12a67e279 100644
--- a/framework/spring/lifecycle/pom.xml
+++ b/framework/spring/lifecycle/pom.xml
@@ -16,7 +16,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-maven-standard</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../../maven-standard/pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/framework/spring/module/pom.xml b/framework/spring/module/pom.xml
index 39b9be196df..6cdadd92e39 100644
--- a/framework/spring/module/pom.xml
+++ b/framework/spring/module/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-maven-standard</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../../maven-standard/pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/maven-standard/pom.xml b/maven-standard/pom.xml
index 1b2531fa988..6e3d8d93fde 100644
--- a/maven-standard/pom.xml
+++ b/maven-standard/pom.xml
@@ -25,7 +25,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<build>
diff --git a/packaging/centos63/cloud-management.rc b/packaging/centos63/cloud-management.rc
index 5b6ba4faa46..0ef5fc4a171 100755
--- a/packaging/centos63/cloud-management.rc
+++ b/packaging/centos63/cloud-management.rc
@@ -1,4 +1,15 @@
#!/bin/bash
+
+### BEGIN INIT INFO
+# Provides: cloudstack-management
+# Required-Start: $network $local_fs
+# Required-Stop: $network $local_fs
+# Default-Start: 3 4 5
+# Default-Stop: 0 1 2 6
+# Short-Description: Start/stop Apache CloudStack Usage Monitor
+# Description: This scripts Starts/Stops the Apache CloudStack Management Server
+### END INIT INFO
+
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
@@ -6,111 +17,131 @@
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
-#
+#
# http://www.apache.org/licenses/LICENSE-2.0
-#
+#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-#
-# cloudstack-management This shell script takes care of starting and stopping Tomcat
-#
-# chkconfig: - 80 20
-#
-### BEGIN INIT INFO
-# Provides: tomcat6
-# Required-Start: $network $syslog
-# Required-Stop: $network $syslog
-# Default-Start:
-# Default-Stop:
-# Description: Release implementation for Servlet 2.5 and JSP 2.1
-# Short-Description: start and stop tomcat
-### END INIT INFO
-#
-# - originally written by Henri Gomez, Keith Irwin, and Nicolas Mailhot
-# - heavily rewritten by Deepak Bhole and Jason Corley
-#
-if [ -r /etc/rc.d/init.d/functions ]; then
- . /etc/rc.d/init.d/functions
-fi
-if [ -r /lib/lsb/init-functions ]; then
- . /lib/lsb/init-functions
-fi
+. /etc/rc.d/init.d/functions
+SHORTNAME="cloudstack-management"
+PIDFILE=/var/run/"$SHORTNAME".pid
+LOCKFILE=/var/lock/subsys/"$SHORTNAME"
+LOGDIR=/var/log/cloudstack/management
+PROGNAME="CloudStack Management Server"
+CLASS="org.apache.cloudstack.ServerDaemon"
+PROG="jsvc"
+DAEMON="/usr/bin/jsvc"
+USER=cloud
-NAME="$(basename $(readlink -f $0))"
-export SERVICE_NAME="$NAME"
-stop() {
- SHUTDOWN_WAIT="30"
- count="0"
- if [ -f /var/run/${NAME}.pid ]; then
- pid=`cat /var/run/${NAME}.pid`
- kill $pid &>/dev/null
- until [ "$(ps --pid $pid | grep -c $pid)" -eq "0" ] || \
- [ "$count" -gt "$SHUTDOWN_WAIT" ]
- do
- sleep 1
- let count="${count}+1"
- done
- if [ "$(ps --pid $pid | grep -c $pid)" -eq "0" ]; then
- log_success_msg "Stopping ${NAME}:"
- rm -f /var/run/${NAME}.pid
- rm -f /var/lock/subsys/${NAME}
- else
- log_failure_msg "Stopping ${NAME}:"
- fi
- else
- echo "Cannot find PID file of ${NAME}"
- log_failure_msg "Stopping ${NAME}:"
- fi
+export HOME="/var/cloudstack/management"
+
+unset OPTIONS
+[ -r /etc/default/"$SHORTNAME" ] && source /etc/default/"$SHORTNAME"
+
+setJavaHome() {
+ # use $JAVA_HOME if defined
+ if [ -n "$JAVA_HOME" ] ; then
+ return
+ fi
+
+ # try java first
+ java=$(which java 2>/dev/null || :)
+
+ # try javac if java is not found
+ if [ -z "$java" ] ; then
+ java=$(which javac 2>/dev/null || :)
+ fi
+
+ if [ -n "$java" ] ; then
+ JAVA_HOME=$(dirname $(dirname $(readlink -e $java)))
+ export JAVA_HOME
+ return
+ fi
+
+ # didnt find java home. exiting with error
+ exit 1
}
-set_ulimit() {
- fd_limit=`ulimit -n`
- if [ "$fd_limit" != "4096" ]; then
- user=`whoami`
- if [ $user == "root" ]; then
- ulimit -n 4096
+setJavaHome
+
+JARS=$(ls /usr/share/cloudstack-management/lib/*.jar | tr '\n' ':' | sed s'/.$//')
+CLASSPATH="$JARS:$CLASSPATH"
+
+start() {
+ if [ -s "$PIDFILE" ] && kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then
+ echo "$PROGNAME apparently already running"
+ exit 0
+ fi
+
+ if hostname --fqdn >/dev/null 2>&1 ; then
+ true
+ else
+ echo "The host name does not resolve properly to an IP address. Cannot start $PROGNAME"
+ exit 1
+ fi
+
+ echo -n "Starting $PROGNAME" "$SHORTNAME"
+
+ if daemon --pidfile $PIDFILE $DAEMON -home "$JAVA_HOME" -cp "$CLASSPATH" -pidfile "$PIDFILE" -user "$USER" \
+ -errfile $LOGDIR/cloudstack-management.err $JAVA_OPTS $CLASS
+ RETVAL=$?
+ then
+ rc=0
+ sleep 1
+ if ! kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then
+ failure
+ rc=1
fi
+ else
+ rc=1
fi
-}
-handle_pid_file() {
- if [ "$1" -ne 0 ] && [ "$1" -ne 3 ]; then
- echo "The pid file locates at /var/run/${NAME}.pid and lock file at /var/lock/subsys/${NAME}.
- Starting ${NAME} will take care of them or you can manually clean up."
+ if [ $rc -eq 0 ]; then
+ success
+ else
+ failure
+ rm -f "$PIDFILE"
fi
+ echo
}
-start() {
- umask 0022
- readpath=$(readlink -f $0)
- source `dirname $readpath`/tomcat.sh
+stop() {
+ echo -n "Stopping $PROGNAME" "$SHORTNAME"
+ killproc -p $PIDFILE $DAEMON
+ if [ "$?" -eq 0 ]; then
+ success
+ else
+ failure
+ fi
+ rm -f "$PIDFILE"
+ echo
}
-# See how we were called.
case "$1" in
- status)
- status ${NAME}
- RETVAL=$?
- handle_pid_file $RETVAL
- ;;
+ start)
+ start
+ ;;
stop)
- stop
- ;;
- restart)
- stop
- set start
- set_ulimit
- start
- ;;
- *)
- set_ulimit
- start
+ stop
+ ;;
+ status)
+ status -p $PIDFILE $SHORTNAME
+ RETVAL=$?
+ ;;
+ restart | force-reload)
+ stop
+ sleep 3
+ start
+ ;;
+ *)
+ echo "Usage: $0 {start|stop|restart|force-reload|status}"
+ RETVAL=3
esac
exit $RETVAL
diff --git a/packaging/centos63/cloud-management.sysconfig b/packaging/centos63/cloud-management.sysconfig
deleted file mode 100644
index cbc8b8b36c1..00000000000
--- a/packaging/centos63/cloud-management.sysconfig
+++ /dev/null
@@ -1,23 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# This file is loaded in /etc/init.d/vmopsmanagement
-# ATM we only do two things here:
-
-dummy=1 ; export TOMCAT_CFG=/etc/cloudstack/management/tomcat6.conf ; . /etc/cloudstack/management/tomcat6.conf
-#--------------------------
-
diff --git a/packaging/centos63/cloud.spec b/packaging/centos63/cloud.spec
index abe50bce65e..682bda97de2 100644
--- a/packaging/centos63/cloud.spec
+++ b/packaging/centos63/cloud.spec
@@ -44,7 +44,6 @@ Source0: %{name}-%{_maventag}.tgz
BuildRoot: %{_tmppath}/%{name}-%{_maventag}-%{release}-build
BuildRequires: java-1.8.0-openjdk-devel
-BuildRequires: tomcat6
BuildRequires: ws-commons-util
BuildRequires: jpackage-utils
BuildRequires: gcc
@@ -59,8 +58,10 @@ intelligent IaaS cloud implementation.
%package management
Summary: CloudStack management server UI
-Requires: tomcat6
Requires: java-1.8.0-openjdk
+Requires: jsvc
+Requires: jakarta-commons-daemon
+Requires: jakarta-commons-daemon-jsvc
Requires: python
Requires: bash
Requires: bzip2
@@ -72,8 +73,6 @@ Requires: nfs-utils
Requires: wget
Requires: mysql
Requires: mysql-connector-java
-Requires: ws-commons-util
-Requires: jpackage-utils
Requires: sudo
Requires: /sbin/service
Requires: /sbin/chkconfig
@@ -165,7 +164,6 @@ The CloudStack usage calculation service
%package cli
Summary: Apache CloudStack CLI
-Provides: python-cloudmonkey
Provides: python-marvin
Group: System Environment/Libraries
%description cli
@@ -193,7 +191,6 @@ Apache CloudStack Marvin integration tests
%package mysql-ha
Summary: Apache CloudStack Balancing Strategy for MySQL
Requires: mysql-connector-java
-Requires: tomcat6
Group: System Environmnet/Libraries
%description mysql-ha
Apache CloudStack Balancing Strategy for MySQL
@@ -243,7 +240,7 @@ mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/cache/%{name}/management/temp
mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/%{name}/mnt
mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/%{name}/management
mkdir -p ${RPM_BUILD_ROOT}%{_initrddir}
-mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig
+mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/default
mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/profile.d
mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/sudoers.d
@@ -266,21 +263,13 @@ cp -r plugins/network-elements/cisco-vnmc/scripts/network/cisco/* ${RPM_BUILD_RO
# Management
mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/
-mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client
+mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/lib
mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/setup
mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/management
mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management
-# Specific for tomcat
-mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/Catalina/localhost/client
-ln -sf /usr/share/tomcat6/bin ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/bin
ln -sf /etc/%{name}/management ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/conf
-ln -sf /usr/share/tomcat6/lib ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/lib
ln -sf /var/log/%{name}/management ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/logs
-ln -sf /var/cache/%{name}/management/temp ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/temp
-ln -sf /var/cache/%{name}/management/work ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/work
-
-/bin/touch ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/management/catalina.out
install -D client/target/utilities/bin/cloud-migrate-databases ${RPM_BUILD_ROOT}%{_bindir}/%{name}-migrate-databases
install -D client/target/utilities/bin/cloud-set-guest-password ${RPM_BUILD_ROOT}%{_bindir}/%{name}-set-guest-password
@@ -293,42 +282,33 @@ install -D client/target/utilities/bin/cloud-sysvmadm ${RPM_BUILD_ROOT}%{_bindir
install -D client/target/utilities/bin/cloud-update-xenserver-licenses ${RPM_BUILD_ROOT}%{_bindir}/%{name}-update-xenserver-licenses
cp -r client/target/utilities/scripts/db/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/setup
-cp -r client/target/cloud-client-ui-%{_maventag}/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client
+cp -r client/target/classes/META-INF/webapp ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapp
+cp client/target/cloud-client-ui-%{_maventag}.jar ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/lib/cloudstack-%{_maventag}.jar
+cp client/target/lib/*jar ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/lib/
# Don't package the scripts in the management webapp
rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/scripts
rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/vms
-for name in db.properties log4j-cloud.xml tomcat6-nonssl.conf tomcat6-ssl.conf server-ssl.xml server-nonssl.xml commons-logging.properties \
- catalina.policy catalina.properties classpath.conf tomcat-users.xml web.xml environment.properties java.security.ciphers; do
- mv ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/$name \
- ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/$name
+for name in db.properties server.properties log4j-cloud.xml commons-logging.properties environment.properties java.security.ciphers
+do
+ cp client/target/conf/$name ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/$name
done
-ln -s %{_sysconfdir}/%{name}/management/log4j-cloud.xml \
- ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/log4j-cloud.xml
-
-mv ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/context.xml \
- ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/Catalina/localhost/client
+ln -s log4j-cloud.xml ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/log4j.xml
install python/bindir/cloud-external-ipallocator.py ${RPM_BUILD_ROOT}%{_bindir}/%{name}-external-ipallocator.py
install -D client/target/pythonlibs/jasypt-1.9.2.jar ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/lib/jasypt-1.9.2.jar
install -D packaging/centos63/cloud-ipallocator.rc ${RPM_BUILD_ROOT}%{_initrddir}/%{name}-ipallocator
install -D packaging/centos63/cloud-management.rc ${RPM_BUILD_ROOT}%{_initrddir}/%{name}-management
-install -D packaging/centos63/cloud-management.sysconfig ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig/%{name}-management
install -D server/target/conf/cloudstack-sudoers ${RPM_BUILD_ROOT}%{_sysconfdir}/sudoers.d/%{name}-management
-install -D packaging/centos63/tomcat.sh ${RPM_BUILD_ROOT}%{_initrddir}/tomcat.sh
-install -D server/target/conf/cloudstack-catalina.logrotate ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/%{name}-catalina
+install -D packaging/systemd/cloudstack-management.default ${RPM_BUILD_ROOT}%{_sysconfdir}/default/%{name}-management
+#install -D server/target/conf/cloudstack-catalina.logrotate ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/%{name}-catalina
chmod 440 ${RPM_BUILD_ROOT}%{_sysconfdir}/sudoers.d/%{name}-management
-chmod 770 ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/Catalina
-chmod 770 ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/Catalina/localhost
-chmod 770 ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/Catalina/localhost/client
chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/%{name}/mnt
chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/%{name}/management
-chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/cache/%{name}/management/work
-chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/cache/%{name}/management/temp
chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/management
chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/agent
@@ -434,6 +414,16 @@ if [ "$1" == "2" ] ; then
fi
fi
+# Remove old tomcat symlinks and env config file
+if [ -L "%{_datadir}/%{name}-management/lib" ]
+then
+ rm -f %{_datadir}/%{name}-management/bin
+ rm -f %{_datadir}/%{name}-management/lib
+ rm -f %{_datadir}/%{name}-management/temp
+ rm -f %{_datadir}/%{name}-management/work
+ rm -f %{_sysconfdir}/default/%{name}-management
+fi
+
%post management
/sbin/chkconfig --add cloudstack-management > /dev/null 2>&1 || true
/sbin/chkconfig --level 345 cloudstack-management on > /dev/null 2>&1 || true
@@ -464,46 +454,7 @@ if [ -f "%{_sysconfdir}/cloud.rpmsave/management/db.properties" ]; then
mv %{_sysconfdir}/cloud.rpmsave/management/db.properties %{_sysconfdir}/cloud.rpmsave/management/db.properties.rpmsave
fi
-# Choose server.xml and tomcat.conf links based on old config, if exists
-serverxml=%{_sysconfdir}/%{name}/management/server.xml
-oldserverxml=%{_sysconfdir}/cloud.rpmsave/management/server.xml
-if [ -f $oldserverxml ] || [ -L $oldserverxml ]; then
- if stat -c %N $oldserverxml| grep -q server-ssl ; then
- if [ -f $serverxml ] || [ -L $serverxml ]; then rm -f $serverxml; fi
- ln -s %{_sysconfdir}/%{name}/management/server-ssl.xml $serverxml
- echo Please verify the server.xml in saved folder, and make the required changes manually , saved folder available at $oldserverxml
- else
- if [ -f $serverxml ] || [ -L $serverxml ]; then rm -f $serverxml; fi
- ln -s %{_sysconfdir}/%{name}/management/server-nonssl.xml $serverxml
- echo Please verify the server.xml in saved folder, and make the required changes manually , saved folder available at $oldserverxml
-
- fi
-else
- echo "Unable to determine ssl settings for server.xml, please run cloudstack-setup-management manually"
-fi
-
-
-tomcatconf=%{_sysconfdir}/%{name}/management/tomcat6.conf
-oldtomcatconf=%{_sysconfdir}/cloud.rpmsave/management/tomcat6.conf
-if [ -f $oldtomcatconf ] || [ -L $oldtomcatconf ] ; then
- if stat -c %N $oldtomcatconf| grep -q tomcat6-ssl ; then
- if [ -f $tomcatconf ] || [ -L $tomcatconf ]; then rm -f $tomcatconf; fi
- ln -s %{_sysconfdir}/%{name}/management/tomcat6-ssl.conf $tomcatconf
- echo Please verify the tomcat6.conf in saved folder, and make the required changes manually , saved folder available at $oldtomcatconf
- else
- if [ -f $tomcatconf ] || [ -L $tomcatconf ]; then rm -f $tomcatconf; fi
- ln -s %{_sysconfdir}/%{name}/management/tomcat6-nonssl.conf $tomcatconf
- echo Please verify the tomcat6.conf in saved folder, and make the required changes manually , saved folder available at $oldtomcatconf
- fi
-else
- echo "Unable to determine ssl settings for tomcat.conf, please run cloudstack-setup-management manually"
-fi
-
-if [ -f "%{_sysconfdir}/cloud.rpmsave/management/cloud.keystore" ]; then
- cp -p %{_sysconfdir}/cloud.rpmsave/management/cloud.keystore %{_sysconfdir}/%{name}/management/cloudmanagementserver.keystore
- # make sure we only do this on the first install of this RPM, don't want to overwrite on a reinstall
- mv %{_sysconfdir}/cloud.rpmsave/management/cloud.keystore %{_sysconfdir}/cloud.rpmsave/management/cloud.keystore.rpmsave
-fi
+chown -R cloud:cloud /var/log/cloudstack/management
%preun agent
/sbin/service cloudstack-agent stop || true
@@ -575,45 +526,26 @@ pip install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz
#No default permission as the permission setup is complex
%files management
%defattr(-,root,root,-)
-%dir %attr(0770,root,cloud) %{_sysconfdir}/%{name}/management/Catalina
-%dir %attr(0770,root,cloud) %{_sysconfdir}/%{name}/management/Catalina/localhost
-%dir %attr(0770,root,cloud) %{_sysconfdir}/%{name}/management/Catalina/localhost/client
%dir %{_datadir}/%{name}-management
%dir %attr(0770,root,cloud) %{_localstatedir}/%{name}/mnt
%dir %attr(0770,cloud,cloud) %{_localstatedir}/%{name}/management
%dir %attr(0770,root,cloud) %{_localstatedir}/cache/%{name}/management
-%dir %attr(0770,root,cloud) %{_localstatedir}/cache/%{name}/management/work
-%dir %attr(0770,root,cloud) %{_localstatedir}/cache/%{name}/management/temp
%dir %attr(0770,root,cloud) %{_localstatedir}/log/%{name}/management
-%config(noreplace) %{_sysconfdir}/sysconfig/%{name}-management
+%config(noreplace) %{_sysconfdir}/default/%{name}-management
%config(noreplace) %{_sysconfdir}/sudoers.d/%{name}-management
%config(noreplace) %attr(0640,root,cloud) %{_sysconfdir}/%{name}/management/db.properties
+%config(noreplace) %attr(0640,root,cloud) %{_sysconfdir}/%{name}/management/server.properties
%config(noreplace) %{_sysconfdir}/%{name}/management/log4j-cloud.xml
-%config(noreplace) %{_sysconfdir}/%{name}/management/tomcat6-nonssl.conf
-%config(noreplace) %{_sysconfdir}/%{name}/management/tomcat6-ssl.conf
-%config(noreplace) %{_sysconfdir}/%{name}/management/Catalina/localhost/client/context.xml
-%config(noreplace) %{_sysconfdir}/%{name}/management/catalina.policy
-%config(noreplace) %{_sysconfdir}/%{name}/management/catalina.properties
-%config(noreplace) %{_sysconfdir}/%{name}/management/classpath.conf
-%config(noreplace) %{_sysconfdir}/%{name}/management/server-nonssl.xml
-%config(noreplace) %{_sysconfdir}/%{name}/management/server-ssl.xml
-%config(noreplace) %{_sysconfdir}/%{name}/management/tomcat-users.xml
-%config(noreplace) %{_sysconfdir}/%{name}/management/web.xml
+%config(noreplace) %{_sysconfdir}/%{name}/management/log4j.xml
%config(noreplace) %{_sysconfdir}/%{name}/management/environment.properties
%config(noreplace) %{_sysconfdir}/%{name}/management/java.security.ciphers
%config(noreplace) %{_sysconfdir}/%{name}/management/commons-logging.properties
%attr(0755,root,root) %{_initrddir}/%{name}-management
-%attr(0755,root,root) %{_initrddir}/tomcat.sh
-
%attr(0755,root,root) %{_bindir}/%{name}-setup-management
%attr(0755,root,root) %{_bindir}/%{name}-update-xenserver-licenses
-%{_datadir}/%{name}-management/webapps
-%{_datadir}/%{name}-management/bin
%{_datadir}/%{name}-management/conf
-%{_datadir}/%{name}-management/lib
+%{_datadir}/%{name}-management/lib/*.jar
%{_datadir}/%{name}-management/logs
-%{_datadir}/%{name}-management/temp
-%{_datadir}/%{name}-management/work
%attr(0755,root,root) %{_bindir}/%{name}-setup-databases
%attr(0755,root,root) %{_bindir}/%{name}-migrate-databases
%attr(0755,root,root) %{_bindir}/%{name}-set-guest-password
@@ -624,13 +556,13 @@ pip install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz
%{_datadir}/%{name}-management/setup/db/*.sql
%{_datadir}/%{name}-management/setup/*.sh
%{_datadir}/%{name}-management/setup/server-setup.xml
+%{_datadir}/%{name}-management/webapp/*
%attr(0755,root,root) %{_bindir}/%{name}-external-ipallocator.py
%attr(0755,root,root) %{_initrddir}/%{name}-ipallocator
%dir %attr(0770,root,root) %{_localstatedir}/log/%{name}/ipallocator
%{_defaultdocdir}/%{name}-management-%{version}/LICENSE
%{_defaultdocdir}/%{name}-management-%{version}/NOTICE
-%attr(0644,cloud,cloud) %{_localstatedir}/log/%{name}/management/catalina.out
-%attr(0644,root,root) %{_sysconfdir}/logrotate.d/%{name}-catalina
+#%attr(0644,root,root) %{_sysconfdir}/logrotate.d/%{name}-catalina
%files agent
%attr(0755,root,root) %{_bindir}/%{name}-setup-agent
diff --git a/packaging/centos7/cloud.spec b/packaging/centos7/cloud.spec
index cc63f5f5788..c8d0ebc0fe0 100644
--- a/packaging/centos7/cloud.spec
+++ b/packaging/centos7/cloud.spec
@@ -44,7 +44,6 @@ Source0: %{name}-%{_maventag}.tgz
BuildRoot: %{_tmppath}/%{name}-%{_maventag}-%{release}-build
BuildRequires: java-1.8.0-openjdk-devel
-BuildRequires: tomcat => 7.0
BuildRequires: ws-commons-util
BuildRequires: jpackage-utils
BuildRequires: gcc
@@ -59,8 +58,8 @@ intelligent IaaS cloud implementation.
%package management
Summary: CloudStack management server UI
-Requires: tomcat => 7.0
Requires: java => 1.8.0
+Requires: apache-commons-daemon-jsvc
Requires: python
Requires: bash
Requires: bzip2
@@ -72,8 +71,6 @@ Requires: nfs-utils
Requires: wget
Requires: mysql
Requires: mysql-connector-java
-Requires: ws-commons-util
-Requires: jpackage-utils
Requires: sudo
Requires: /sbin/service
Requires: /sbin/chkconfig
@@ -140,7 +137,6 @@ The CloudStack usage calculation service
%package cli
Summary: Apache CloudStack CLI
-Provides: python-cloudmonkey
Provides: python-marvin
Group: System Environment/Libraries
%description cli
@@ -168,7 +164,6 @@ Apache CloudStack Marvin integration tests
%package mysql-ha
Summary: Apache CloudStack Balancing Strategy for MySQL
Requires: mysql-connector-java
-Requires: tomcat => 7.0
Group: System Environmnet/Libraries
%description mysql-ha
Apache CloudStack Balancing Strategy for MySQL
@@ -234,22 +229,15 @@ cp -r plugins/network-elements/cisco-vnmc/scripts/network/cisco/* ${RPM_BUILD_RO
# Management
mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/
-mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client
+mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/lib
mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/setup
mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/management
mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management
mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/run
-# Specific for tomcat
-mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/Catalina/localhost/client
-ln -sf /usr/share/tomcat/bin ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/bin
+# Setup Jetty
ln -sf /etc/%{name}/management ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/conf
-ln -sf /usr/share/tomcat/lib ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/lib
ln -sf /var/log/%{name}/management ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/logs
-ln -sf /var/cache/%{name}/management/temp ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/temp
-ln -sf /var/cache/%{name}/management/work ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/work
-
-/bin/touch ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/management/catalina.out
install -D client/target/utilities/bin/cloud-migrate-databases ${RPM_BUILD_ROOT}%{_bindir}/%{name}-migrate-databases
install -D client/target/utilities/bin/cloud-set-guest-password ${RPM_BUILD_ROOT}%{_bindir}/%{name}-set-guest-password
@@ -262,25 +250,22 @@ install -D client/target/utilities/bin/cloud-sysvmadm ${RPM_BUILD_ROOT}%{_bindir
install -D client/target/utilities/bin/cloud-update-xenserver-licenses ${RPM_BUILD_ROOT}%{_bindir}/%{name}-update-xenserver-licenses
cp -r client/target/utilities/scripts/db/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/setup
-cp -r client/target/cloud-client-ui-%{_maventag}/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client
+
+cp -r client/target/cloud-client-ui-%{_maventag}.jar ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/
+cp -r client/target/classes/META-INF/webapp ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapp
+mv ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/cloud-client-ui-%{_maventag}.jar ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/lib/cloudstack-%{_maventag}.jar
+cp client/target/lib/*jar ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/lib/
# Don't package the scripts in the management webapp
rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/scripts
rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/vms
-for name in db.properties log4j-cloud.xml server7-nonssl.xml server7-ssl.xml \
- commons-logging.properties catalina.policy catalina.properties classpath.conf \
- tomcat-users.xml web.xml environment.properties java.security.ciphers
+for name in db.properties server.properties log4j-cloud.xml commons-logging.properties environment.properties java.security.ciphers
do
- mv ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/$name \
- ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/$name
+ cp client/target/conf/$name ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/$name
done
-ln -s %{_sysconfdir}/%{name}/management/log4j-cloud.xml \
- ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/log4j-cloud.xml
-
-mv ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/context.xml \
- ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/Catalina/localhost/client
+ln -s log4j-cloud.xml ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/log4j.xml
install python/bindir/cloud-external-ipallocator.py ${RPM_BUILD_ROOT}%{_bindir}/%{name}-external-ipallocator.py
install -D client/target/pythonlibs/jasypt-1.9.2.jar ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/lib/jasypt-1.9.2.jar
@@ -291,12 +276,9 @@ install -D packaging/systemd/cloudstack-management.service ${RPM_BUILD_ROOT}%{_u
install -D packaging/systemd/cloudstack-management.default ${RPM_BUILD_ROOT}%{_sysconfdir}/default/%{name}-management
install -D server/target/conf/cloudstack-sudoers ${RPM_BUILD_ROOT}%{_sysconfdir}/sudoers.d/%{name}-management
touch ${RPM_BUILD_ROOT}%{_localstatedir}/run/%{name}-management.pid
-install -D server/target/conf/cloudstack-catalina.logrotate ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/%{name}-catalina
+#install -D server/target/conf/cloudstack-catalina.logrotate ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/%{name}-catalina
chmod 440 ${RPM_BUILD_ROOT}%{_sysconfdir}/sudoers.d/%{name}-management
-chmod 770 ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/Catalina
-chmod 770 ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/Catalina/localhost
-chmod 770 ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/Catalina/localhost/client
chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/%{name}/mnt
chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/%{name}/management
chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/cache/%{name}/management/work
@@ -392,6 +374,16 @@ if [ "$1" == "2" ] ; then
fi
fi
+# Remove old tomcat symlinks and env config file
+if [ -L "%{_datadir}/%{name}-management/lib" ]
+then
+ rm -f %{_datadir}/%{name}-management/bin
+ rm -f %{_datadir}/%{name}-management/lib
+ rm -f %{_datadir}/%{name}-management/temp
+ rm -f %{_datadir}/%{name}-management/work
+ rm -f %{_sysconfdir}/default/%{name}-management
+fi
+
%post management
/usr/bin/systemctl on cloudstack-management > /dev/null 2>&1 || true
@@ -408,6 +400,8 @@ if [ -f %{_sysconfdir}/sysconfig/%{name}-management ] ; then
mv %{_sysconfdir}/sysconfig/%{name}-management %{_sysconfdir}/default/%{name}-management
fi
+chown -R cloud:cloud /var/log/cloudstack/management
+
%preun agent
/sbin/service cloudstack-agent stop || true
if [ "$1" == "0" ] ; then
@@ -477,44 +471,28 @@ pip install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz
#No default permission as the permission setup is complex
%files management
%defattr(-,root,root,-)
-%dir %attr(0770,root,cloud) %{_sysconfdir}/%{name}/management/Catalina
-%dir %attr(0770,root,cloud) %{_sysconfdir}/%{name}/management/Catalina/localhost
-%dir %attr(0770,root,cloud) %{_sysconfdir}/%{name}/management/Catalina/localhost/client
%dir %{_datadir}/%{name}-management
%dir %attr(0770,root,cloud) %{_localstatedir}/%{name}/mnt
%dir %attr(0770,cloud,cloud) %{_localstatedir}/%{name}/management
%dir %attr(0770,root,cloud) %{_localstatedir}/cache/%{name}/management
-%dir %attr(0770,root,cloud) %{_localstatedir}/cache/%{name}/management/work
-%dir %attr(0770,root,cloud) %{_localstatedir}/cache/%{name}/management/temp
%dir %attr(0770,root,cloud) %{_localstatedir}/log/%{name}/management
%config(noreplace) %{_sysconfdir}/default/%{name}-management
%config(noreplace) %{_sysconfdir}/sudoers.d/%{name}-management
%config(noreplace) %{_sysconfdir}/security/limits.d/cloud
%config(noreplace) %attr(0640,root,cloud) %{_sysconfdir}/%{name}/management/db.properties
+%config(noreplace) %attr(0640,root,cloud) %{_sysconfdir}/%{name}/management/server.properties
%config(noreplace) %{_sysconfdir}/%{name}/management/log4j-cloud.xml
-%config(noreplace) %{_sysconfdir}/%{name}/management/Catalina/localhost/client/context.xml
-%config(noreplace) %{_sysconfdir}/%{name}/management/catalina.policy
-%config(noreplace) %{_sysconfdir}/%{name}/management/catalina.properties
-%config(noreplace) %{_sysconfdir}/%{name}/management/classpath.conf
-%config(noreplace) %{_sysconfdir}/%{name}/management/server7-nonssl.xml
-%config(noreplace) %{_sysconfdir}/%{name}/management/server7-ssl.xml
-%config(noreplace) %{_sysconfdir}/%{name}/management/tomcat-users.xml
-%config(noreplace) %{_sysconfdir}/%{name}/management/web.xml
+%config(noreplace) %{_sysconfdir}/%{name}/management/log4j.xml
%config(noreplace) %{_sysconfdir}/%{name}/management/environment.properties
%config(noreplace) %{_sysconfdir}/%{name}/management/java.security.ciphers
%config(noreplace) %{_sysconfdir}/%{name}/management/commons-logging.properties
%attr(0755,root,root) %{_unitdir}/%{name}-management.service
%attr(0755,cloud,cloud) %{_localstatedir}/run/%{name}-management.pid
-
%attr(0755,root,root) %{_bindir}/%{name}-setup-management
%attr(0755,root,root) %{_bindir}/%{name}-update-xenserver-licenses
-%{_datadir}/%{name}-management/webapps
-%{_datadir}/%{name}-management/bin
%{_datadir}/%{name}-management/conf
-%{_datadir}/%{name}-management/lib
+%{_datadir}/%{name}-management/lib/*.jar
%{_datadir}/%{name}-management/logs
-%{_datadir}/%{name}-management/temp
-%{_datadir}/%{name}-management/work
%attr(0755,root,root) %{_bindir}/%{name}-setup-databases
%attr(0755,root,root) %{_bindir}/%{name}-migrate-databases
%attr(0755,root,root) %{_bindir}/%{name}-set-guest-password
@@ -525,13 +503,13 @@ pip install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz
%{_datadir}/%{name}-management/setup/db/*.sql
%{_datadir}/%{name}-management/setup/*.sh
%{_datadir}/%{name}-management/setup/server-setup.xml
+%{_datadir}/%{name}-management/webapp/*
%attr(0755,root,root) %{_bindir}/%{name}-external-ipallocator.py
%attr(0755,root,root) %{_initrddir}/%{name}-ipallocator
%dir %attr(0770,root,root) %{_localstatedir}/log/%{name}/ipallocator
%{_defaultdocdir}/%{name}-management-%{version}/LICENSE
%{_defaultdocdir}/%{name}-management-%{version}/NOTICE
-%attr(0644,cloud,cloud) %{_localstatedir}/log/%{name}/management/catalina.out
-%attr(0644,root,root) %{_sysconfdir}/logrotate.d/%{name}-catalina
+#%attr(0644,root,root) %{_sysconfdir}/logrotate.d/%{name}-catalina
%files agent
%attr(0755,root,root) %{_bindir}/%{name}-setup-agent
diff --git a/packaging/centos7/tomcat7/catalina.properties b/packaging/centos7/tomcat7/catalina.properties
deleted file mode 100644
index e0baf61261d..00000000000
--- a/packaging/centos7/tomcat7/catalina.properties
+++ /dev/null
@@ -1,81 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-#
-# List of comma-separated packages that start with or equal this string
-# will cause a security exception to be thrown when
-# passed to checkPackageAccess unless the
-# corresponding RuntimePermission ("accessClassInPackage."+package) has
-# been granted.
-package.access=sun.,org.apache.catalina.,org.apache.coyote.,org.apache.tomcat.,org.apache.jasper.,sun.beans.
-#
-# List of comma-separated packages that start with or equal this string
-# will cause a security exception to be thrown when
-# passed to checkPackageDefinition unless the
-# corresponding RuntimePermission ("defineClassInPackage."+package) has
-# been granted.
-#
-# by default, no packages are restricted for definition, and none of
-# the class loaders supplied with the JDK call checkPackageDefinition.
-#
-package.definition=sun.,java.,org.apache.catalina.,org.apache.coyote.,org.apache.tomcat.,org.apache.jasper.
-
-#
-#
-# List of comma-separated paths defining the contents of the "common"
-# classloader. Prefixes should be used to define what is the repository type.
-# Path may be relative to the CATALINA_HOME or CATALINA_BASE path or absolute.
-# If left as blank,the JVM system loader will be used as Catalina's "common"
-# loader.
-# Examples:
-# "foo": Add this folder as a class repository
-# "foo/*.jar": Add all the JARs of the specified folder as class
-# repositories
-# "foo/bar.jar": Add bar.jar as a class repository
-common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar,/usr/share/java/mysql-connector-java.jar,/usr/share/cloudstack-mysql-ha/lib/*.jar
-
-#
-# List of comma-separated paths defining the contents of the "server"
-# classloader. Prefixes should be used to define what is the repository type.
-# Path may be relative to the CATALINA_HOME or CATALINA_BASE path or absolute.
-# If left as blank, the "common" loader will be used as Catalina's "server"
-# loader.
-# Examples:
-# "foo": Add this folder as a class repository
-# "foo/*.jar": Add all the JARs of the specified folder as class
-# repositories
-# "foo/bar.jar": Add bar.jar as a class repository
-server.loader=
-
-#
-# List of comma-separated paths defining the contents of the "shared"
-# classloader. Prefixes should be used to define what is the repository type.
-# Path may be relative to the CATALINA_BASE path or absolute. If left as blank,
-# the "common" loader will be used as Catalina's "shared" loader.
-# Examples:
-# "foo": Add this folder as a class repository
-# "foo/*.jar": Add all the JARs of the specified folder as class
-# repositories
-# "foo/bar.jar": Add bar.jar as a class repository
-# Please note that for single jars, e.g. bar.jar, you need the URL form
-# starting with file:.
-shared.loader=
-
-#
-# String cache configuration.
-tomcat.util.buf.StringCache.byte.enabled=true
-#tomcat.util.buf.StringCache.char.enabled=true
-#tomcat.util.buf.StringCache.trainThreshold=500000
-#tomcat.util.buf.StringCache.cacheSize=5000
diff --git a/packaging/centos7/tomcat7/commons-logging.properties b/packaging/centos7/tomcat7/commons-logging.properties
deleted file mode 100644
index 1e570d65f3b..00000000000
--- a/packaging/centos7/tomcat7/commons-logging.properties
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# This is the logging properties that goes to the war, there are two logging conf kept at the
-# svn, one for developement (one at src/test-resources) and other for producation
-
-# Uncomment the next line to disable all logging.
-#org.apache.commons.logging.Log=org.apache.commons.logging.impl.NoOpLog
-
-# Uncomment the next line to enable the simple log based logging
-#org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
-
-# Uncomment the next line to enable log4j based logging
-org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
diff --git a/packaging/centos7/tomcat7/db.properties b/packaging/centos7/tomcat7/db.properties
deleted file mode 100644
index 94376f7286b..00000000000
--- a/packaging/centos7/tomcat7/db.properties
+++ /dev/null
@@ -1,106 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# management server clustering parameters, change cluster.node.IP to the machine IP address
-# in which the management server(Tomcat) is running
-cluster.node.IP=127.0.0.1
-cluster.servlet.port=9090
-region.id=1
-
-# CloudStack database settings
-db.cloud.username=cloud
-db.cloud.password=ENC(vlzQjmqOV4s5q7n+S1OMbA==)
-db.cloud.host=localhost
-db.cloud.driver=jdbc:mysql
-db.cloud.port=3306
-db.cloud.name=cloud
-
-# CloudStack database tuning parameters
-db.cloud.maxActive=250
-db.cloud.maxIdle=30
-db.cloud.maxWait=10000
-db.cloud.validationQuery=SELECT 1
-db.cloud.testOnBorrow=true
-db.cloud.testWhileIdle=true
-db.cloud.timeBetweenEvictionRunsMillis=40000
-db.cloud.minEvictableIdleTimeMillis=240000
-db.cloud.poolPreparedStatements=false
-db.cloud.url.params=prepStmtCacheSize=517&cachePrepStmts=true&sessionVariables=sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'
-
-# CloudStack database SSL settings
-db.cloud.useSSL=false
-db.cloud.keyStore=
-db.cloud.keyStorePassword=
-db.cloud.trustStore=
-db.cloud.trustStorePassword=
-db.cloud.keyStorePassphrase=vmops.com
-
-# Encryption Settings
-db.cloud.encryption.type=file
-db.cloud.encrypt.secret=ENC(zaGuSF5a4KyWayn2t0yyjDa0HjdToVtZ)
-
-# usage database settings
-db.usage.password=ENC(cQEcN5aVucSYK+WUkPjDcw==)
-db.usage.username=cloud
-db.usage.host=localhost
-# It's not guaranteed that using a different DB provider than the one from the regular cloud DB will work
-db.usage.driver=jdbc:mysql
-db.usage.port=3306
-db.usage.name=cloud_usage
-
-# usage database tuning parameters
-db.usage.maxActive=100
-db.usage.maxIdle=30
-db.usage.maxWait=10000
-db.usage.url.params=
-
-# Simulator database settings
-db.simulator.username=cloud
-db.simulator.password=cloud
-db.simulator.host=localhost
-# It's not guaranteed that using a different DB provider than the one from the regular cloud DB will work
-db.simulator.driver=jdbc:mysql
-db.simulator.port=3306
-db.simulator.name=simulator
-db.simulator.maxActive=250
-db.simulator.maxIdle=30
-db.simulator.maxWait=10000
-db.simulator.autoReconnect=true
-
-
-# High Availability And Cluster Properties
-db.ha.enabled=false
-db.ha.loadBalanceStrategy=com.cloud.utils.db.StaticStrategy
-# cloud stack Database
-db.cloud.slaves=localhost,localhost
-db.cloud.autoReconnect=true
-db.cloud.failOverReadOnly=false
-db.cloud.reconnectAtTxEnd=true
-db.cloud.autoReconnectForPools=true
-db.cloud.secondsBeforeRetryMaster=3600
-db.cloud.queriesBeforeRetryMaster=5000
-db.cloud.initialTimeout=3600
-
-#usage Database
-db.usage.slaves=localhost,localhost
-db.usage.autoReconnect=true
-db.usage.failOverReadOnly=false
-db.usage.reconnectAtTxEnd=true
-db.usage.autoReconnectForPools=true
-db.usage.secondsBeforeRetryMaster=3600
-db.usage.queriesBeforeRetryMaster=5000
-db.usage.initialTimeout=3600
diff --git a/packaging/centos7/tomcat7/environment.properties b/packaging/centos7/tomcat7/environment.properties
deleted file mode 100644
index 3254cf64e18..00000000000
--- a/packaging/centos7/tomcat7/environment.properties
+++ /dev/null
@@ -1,22 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# management server compile-time environment parameters
-
-paths.script=/usr/share/cloudstack-common
-mount.parent=/var/cloudstack/mnt
-cloud-stack-components-specification=components.xml
diff --git a/packaging/centos7/tomcat7/java.security.ciphers b/packaging/centos7/tomcat7/java.security.ciphers
deleted file mode 100644
index 986abf61e71..00000000000
--- a/packaging/centos7/tomcat7/java.security.ciphers
+++ /dev/null
@@ -1,18 +0,0 @@
- # Licensed to the Apache Software Foundation (ASF) under one
- # or more contributor license agreements. See the NOTICE file
- # distributed with this work for additional information
- # regarding copyright ownership. The ASF licenses this file
- # to you under the Apache License, Version 2.0 (the
- # "License"); you may not use this file except in compliance
- # with the License. You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing,
- # software distributed under the License is distributed on an
- # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- # KIND, either express or implied. See the License for the
- # specific language governing permissions and limitations
- # under the License.
-
-jdk.tls.disabledAlgorithms=DH keySize < 128, RSA keySize < 128, DES keySize < 128, SHA1 keySize < 128, MD5 keySize < 128, RC4
\ No newline at end of file
diff --git a/packaging/centos7/tomcat7/log4j-cloud.xml b/packaging/centos7/tomcat7/log4j-cloud.xml
deleted file mode 100644
index 1ebcbf8dc71..00000000000
--- a/packaging/centos7/tomcat7/log4j-cloud.xml
+++ /dev/null
@@ -1,199 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements. See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership. The ASF licenses this file
-to you under the Apache License, Version 2.0 (the
-"License"); you may not use this file except in compliance
-with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, either express or implied. See the License for the
-specific language governing permissions and limitations
-under the License.
--->
-<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
- <throwableRenderer class="com.cloud.utils.log.CglibThrowableRenderer"/>
-
- <!-- ================================= -->
- <!-- Preserve messages in a local file -->
- <!-- ================================= -->
-
- <!-- A regular appender FIXME implement code that will close/reopen logs on SIGHUP by logrotate FIXME make the paths configurable using the build system -->
- <appender name="FILE" class="org.apache.log4j.rolling.RollingFileAppender">
- <param name="Append" value="true"/>
- <param name="Threshold" value="TRACE"/>
- <rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
- <param name="FileNamePattern" value="/var/log/cloudstack/management/management-server.log.%d{yyyy-MM-dd}.gz"/>
- <param name="ActiveFileName" value="/var/log/cloudstack/management/management-server.log"/>
- </rollingPolicy>
- <layout class="org.apache.log4j.EnhancedPatternLayout">
- <param name="ConversionPattern" value="%d{ISO8601} %-5p [%c{1.}] (%t:%x) %m%n"/>
- </layout>
- </appender>
-
- <appender name="APISERVER" class="org.apache.log4j.rolling.RollingFileAppender">
- <param name="Append" value="true"/>
- <param name="Threshold" value="DEBUG"/>
- <rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
- <param name="FileNamePattern" value="/var/log/cloudstack/management/apilog.log.%d{yyyy-MM-dd}.gz"/>
- <param name="ActiveFileName" value="/var/log/cloudstack/management/apilog.log"/>
- </rollingPolicy>
- <layout class="org.apache.log4j.EnhancedPatternLayout">
- <param name="ConversionPattern" value="%d{ISO8601} %-5p [%c{1.}] (%t:%x) %m%n"/>
- </layout>
- </appender>
-
- <!-- ============================== -->
- <!-- Append warnings+ to the syslog if it is listening on UDP port FIXME make sysloghost configurable! -->
- <!-- ============================== -->
-
- <appender name="SYSLOG" class="org.apache.log4j.net.SyslogAppender">
- <param name="Threshold" value="WARN"/>
- <param name="SyslogHost" value="localhost"/>
- <param name="Facility" value="LOCAL6"/>
- <layout class="org.apache.log4j.PatternLayout">
- <param name="ConversionPattern" value="%-5p [%c{3}] (%t:%x) %m%n"/>
- </layout>
- </appender>
-
- <!-- ============================== -->
- <!-- Append alerts to the syslog if it is configured -->
- <!-- ============================== -->
-
- <appender name="ALERTSYSLOG" class="org.apache.cloudstack.syslog.AlertsSyslogAppender">
- <param name="Threshold" value="WARN"/>
- <param name="SyslogHosts" value=""/>
- <param name="Facility" value="LOCAL6"/>
- <layout class="org.apache.log4j.PatternLayout">
- <param name="ConversionPattern" value="%-5p [%c{3}] (%t:%x) %m%n"/>
- </layout>
- </appender>
-
- <!-- ============================== -->
- <!-- send alert warnings+ as the SNMP trap if it is configured! -->
- <!-- ============================== -->
-
- <appender name="SNMP" class="org.apache.cloudstack.alert.snmp.SnmpTrapAppender">
- <param name="Threshold" value="WARN"/>
- <param name="SnmpManagerIpAddresses" value=""/>
- <param name="SnmpManagerPorts" value=""/>
- <param name="SnmpManagerCommunities" value=""/>
- <layout class="org.apache.cloudstack.alert.snmp.SnmpEnhancedPatternLayout">
- <param name="PairDelimiter" value="//"/>
- <param name="KeyValueDelimiter" value="::"/>
- </layout>
- </appender>
-
- <!-- ============================== -->
- <!-- Append messages to the console -->
- <!-- ============================== -->
-
- <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
- <param name="Target" value="System.out"/>
- <param name="Threshold" value="INFO"/>
- <layout class="org.apache.log4j.EnhancedPatternLayout">
- <param name="ConversionPattern" value="%-5p [%c{1.}] (%t:%x) %m%n"/>
- </layout>
- </appender>
-
- <!-- ================ -->
- <!-- Limit categories -->
- <!-- ================ -->
-
- <category name="com.cloud">
- <priority value="DEBUG"/>
- </category>
-
- <category name="org.apache.cloudstack">
- <priority value="DEBUG"/>
- </category>
-
- <category name="org.apache.cloudstack">
- <priority value="DEBUG"/>
- </category>
-
- <category name="com.cloud.utils.nio">
- <priority value="INFO"/>
- </category>
-
- <!-- Limit the org.apache category to INFO as its DEBUG is verbose -->
- <category name="org.apache">
- <priority value="INFO"/>
- </category>
-
- <category name="org.apache.cloudstack">
- <priority value="DEBUG"/>
- </category>
-
- <category name="org.apache.cloudstack.api.command">
- <priority value="TRACE"/>
- </category>
-
- <category name="org">
- <priority value="INFO"/>
- </category>
-
- <category name="org.springframework">
- <priority value="WARN"/>
- </category>
-
- <category name="org.apache.cloudstack.spring.module.context.ResourceApplicationContext">
- <priority value="WARN"/>
- </category>
-
- <category name="net">
- <priority value="INFO"/>
- </category>
-
- <category name="apiserver.com.cloud">
- <priority value="DEBUG"/>
- </category>
-
- <logger name="apiserver.com.cloud" additivity="false">
- <level value="DEBUG"/>
- <appender-ref ref="APISERVER"/>
- </logger>
-
- <!-- Limit the com.amazonaws category to INFO as its DEBUG is verbose -->
- <category name="com.amazonaws">
- <priority value="INFO"/>
- </category>
-
- <!-- Limit the httpclient.wire category to INFO as its DEBUG is verbose -->
- <category name="httpclient.wire">
- <priority value="INFO"/>
- </category>
-
- <!-- ============================== -->
- <!-- Add or remove these logger for SNMP, this logger is for SNMP alerts plugin -->
- <!-- ============================== -->
-
- <logger name="org.apache.cloudstack.alerts" additivity="false">
- <level value="WARN"/>
- <appender-ref ref="SYSLOG"/>
- <appender-ref ref="CONSOLE"/>
- <appender-ref ref="FILE"/>
- <appender-ref ref="SNMP"/>
- <appender-ref ref="ALERTSYSLOG"/>
- </logger>
-
- <!-- ======================= -->
- <!-- Setup the Root category -->
- <!-- ======================= -->
-
- <root>
- <level value="INFO"/>
- <appender-ref ref="SYSLOG"/>
- <appender-ref ref="CONSOLE"/>
- <appender-ref ref="FILE"/>
- </root>
-
-</log4j:configuration>
diff --git a/packaging/centos7/tomcat7/server.xml b/packaging/centos7/tomcat7/server.xml
deleted file mode 100644
index 124ff63bc7f..00000000000
--- a/packaging/centos7/tomcat7/server.xml
+++ /dev/null
@@ -1,80 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- Note: A "Server" is not itself a "Container", so you may not
- define subcomponents such as "Valves" at this level.
- Documentation at /docs/config/server.html
- -->
-<Server port="8005" shutdown="SHUTDOWN">
- <!-- Security listener. Documentation at /docs/config/listeners.html
- <Listener className="org.apache.catalina.security.SecurityListener" />
- -->
- <!--APR library loader. Documentation at /docs/apr.html -->
- <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
- <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
- <Listener className="org.apache.catalina.core.JasperListener" />
- <!-- Prevent memory leaks due to use of particular java/javax APIs-->
- <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
- <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
- <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
-
- <!-- Global JNDI resources
- Documentation at /docs/jndi-resources-howto.html
- -->
- <GlobalNamingResources>
- <!-- Editable user database that can also be used by
- UserDatabaseRealm to authenticate users
- -->
- <Resource name="UserDatabase" auth="Container"
- type="org.apache.catalina.UserDatabase"
- description="User database that can be updated and saved"
- factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
- pathname="conf/tomcat-users.xml" />
- </GlobalNamingResources>
-
- <Service name="CloudStackManagement">
-
- <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
- maxThreads="150" minSpareThreads="25"/>
-
- <Connector executor="tomcatThreadPool"
- port="8080" protocol="HTTP/1.1"
- connectionTimeout="20000"
- acceptCount="150"
- enableLookups="false"
- maxThreads="150"
- maxHttpHeaderSize="8192"
- redirectPort="8443" />
-
- <Engine name="Catalina" defaultHost="localhost">
-
- <Realm className="org.apache.catalina.realm.LockOutRealm">
- <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
- resourceName="UserDatabase"/>
- </Realm>
-
- <Host name="localhost" appBase="webapps"
- unpackWARs="true" autoDeploy="true">
-
- <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
- prefix="localhost_access_log." suffix=".txt"
- pattern="%h %l %u %t "%r" %s %b" />
-
- </Host>
- </Engine>
- </Service>
-</Server>
diff --git a/packaging/centos7/tomcat7/tomcat-users.xml b/packaging/centos7/tomcat7/tomcat-users.xml
deleted file mode 100644
index 81422a02892..00000000000
--- a/packaging/centos7/tomcat7/tomcat-users.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<tomcat-users>
-<!--
- <role rolename="tomcat"/>
- <role rolename="role1"/>
- <user username="tomcat" password="tomcat" roles="tomcat"/>
- <user username="both" password="tomcat" roles="tomcat,role1"/>
- <user username="role1" password="tomcat" roles="role1"/>
--->
-
-<!-- The host manager webapp is restricted to users with role "admin" -->
-<!--<user name="tomcat" password="password" roles="admin" />-->
-<!-- The manager webapp is restricted to users with role "manager" -->
-<!--<user name="tomcat" password="password" roles="manager" />-->
-</tomcat-users>
diff --git a/packaging/centos7/tomcat7/web.xml b/packaging/centos7/tomcat7/web.xml
deleted file mode 100644
index 8645a64da42..00000000000
--- a/packaging/centos7/tomcat7/web.xml
+++ /dev/null
@@ -1,1187 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<web-app xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
- version="2.5">
-
- <!-- ======================== Introduction ============================== -->
- <!-- This document defines default values for *all* web applications -->
- <!-- loaded into this instance of Tomcat. As each application is -->
- <!-- deployed, this file is processed, followed by the -->
- <!-- "/WEB-INF/web.xml" deployment descriptor from your own -->
- <!-- applications. -->
- <!-- -->
- <!-- WARNING: Do not configure application-specific resources here! -->
- <!-- They should go in the "/WEB-INF/web.xml" file in your application. -->
-
-
- <!-- ================== Built In Servlet Definitions ==================== -->
-
-
- <!-- The default servlet for all web applications, that serves static -->
- <!-- resources. It processes all requests that are not mapped to other -->
- <!-- servlets with servlet mappings (defined either here or in your own -->
- <!-- web.xml file. This servlet supports the following initialization -->
- <!-- parameters (default values are in square brackets): -->
- <!-- -->
- <!-- debug Debugging detail level for messages logged -->
- <!-- by this servlet. [0] -->
- <!-- -->
- <!-- fileEncoding Encoding to be used to read static resources -->
- <!-- [platform default] -->
- <!-- -->
- <!-- input Input buffer size (in bytes) when reading -->
- <!-- resources to be served. [2048] -->
- <!-- -->
- <!-- listings Should directory listings be produced if there -->
- <!-- is no welcome file in this directory? [false] -->
- <!-- WARNING: Listings for directories with many -->
- <!-- entries can be slow and may consume -->
- <!-- significant proportions of server resources. -->
- <!-- -->
- <!-- output Output buffer size (in bytes) when writing -->
- <!-- resources to be served. [2048] -->
- <!-- -->
- <!-- readonly Is this context "read only", so HTTP -->
- <!-- commands like PUT and DELETE are -->
- <!-- rejected? [true] -->
- <!-- -->
- <!-- readmeFile File name to display with the directory -->
- <!-- contents. [null] -->
- <!-- -->
- <!-- sendfileSize If the connector used supports sendfile, this -->
- <!-- represents the minimal file size in KB for -->
- <!-- which sendfile will be used. Use a negative -->
- <!-- value to always disable sendfile. [48] -->
- <!-- -->
- <!-- useAcceptRanges Should the Accept-Ranges header be included -->
- <!-- in responses where appropriate? [true] -->
- <!-- -->
- <!-- For directory listing customization. Checks localXsltFile, then -->
- <!-- globalXsltFile, then defaults to original behavior. -->
- <!-- -->
- <!-- localXsltFile Make directory listings an XML doc and -->
- <!-- pass the result to this style sheet residing -->
- <!-- in that directory. This overrides -->
- <!-- globalXsltFile[null] -->
- <!-- -->
- <!-- globalXsltFile Site wide configuration version of -->
- <!-- localXsltFile This argument is expected -->
- <!-- to be a physical file. [null] -->
- <!-- -->
- <!-- -->
-
- <servlet>
- <servlet-name>default</servlet-name>
- <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
- <init-param>
- <param-name>debug</param-name>
- <param-value>0</param-value>
- </init-param>
- <init-param>
- <param-name>listings</param-name>
- <param-value>false</param-value>
- </init-param>
- <load-on-startup>1</load-on-startup>
- </servlet>
-
-
- <!-- This servlet has been deprecated due to security concerns. Servlets -->
- <!-- should be explicitly mapped in web.xml -->
- <!-- -->
- <!-- The "invoker" servlet, which executes anonymous servlet classes -->
- <!-- that have not been defined in a web.xml file. Traditionally, this -->
- <!-- servlet is mapped to the URL pattern "/servlet/*", but you can map -->
- <!-- it to other patterns as well. The extra path info portion of such a -->
- <!-- request must be the fully qualified class name of a Java class that -->
- <!-- implements Servlet (or extends HttpServlet), or the servlet name -->
- <!-- of an existing servlet definition. This servlet supports the -->
- <!-- following initialization parameters (default values are in square -->
- <!-- brackets): -->
- <!-- -->
- <!-- debug Debugging detail level for messages logged -->
- <!-- by this servlet. [0] -->
-
-<!--
- <servlet>
- <servlet-name>invoker</servlet-name>
- <servlet-class>
- org.apache.catalina.servlets.InvokerServlet
- </servlet-class>
- <init-param>
- <param-name>debug</param-name>
- <param-value>0</param-value>
- </init-param>
- <load-on-startup>2</load-on-startup>
- </servlet>
--->
-
-
- <!-- The JSP page compiler and execution servlet, which is the mechanism -->
- <!-- used by Tomcat to support JSP pages. Traditionally, this servlet -->
- <!-- is mapped to the URL pattern "*.jsp". This servlet supports the -->
- <!-- following initialization parameters (default values are in square -->
- <!-- brackets): -->
- <!-- -->
- <!-- checkInterval If development is false and checkInterval is -->
- <!-- greater than zero, background compilations are -->
- <!-- enabled. checkInterval is the time in seconds -->
- <!-- between checks to see if a JSP page (and its -->
- <!-- dependent files) needs to be recompiled. [0] -->
- <!-- -->
- <!-- classdebuginfo Should the class file be compiled with -->
- <!-- debugging information? [true] -->
- <!-- -->
- <!-- classpath What class path should I use while compiling -->
- <!-- generated servlets? [Created dynamically -->
- <!-- based on the current web application] -->
- <!-- -->
- <!-- compiler Which compiler Ant should use to compile JSP -->
- <!-- pages. See the jasper documentation for more -->
- <!-- information. -->
- <!-- -->
- <!-- compilerSourceVM Compiler source VM. [1.5] -->
- <!-- -->
- <!-- compilerTargetVM Compiler target VM. [1.5] -->
- <!-- -->
- <!-- development Is Jasper used in development mode? If true, -->
- <!-- the frequency at which JSPs are checked for -->
- <!-- modification may be specified via the -->
- <!-- modificationTestInterval parameter. [true] -->
- <!-- -->
- <!-- displaySourceFragment -->
- <!-- Should a source fragment be included in -->
- <!-- exception messages? [true] -->
- <!-- -->
- <!-- dumpSmap Should the SMAP info for JSR45 debugging be -->
- <!-- dumped to a file? [false] -->
- <!-- False if suppressSmap is true -->
- <!-- -->
- <!-- enablePooling Determines whether tag handler pooling is -->
- <!-- enabled. This is a compilation option. It will -->
- <!-- not alter the behaviour of JSPs that have -->
- <!-- already been compiled. [true] -->
- <!-- -->
- <!-- engineOptionsClass Allows specifying the Options class used to -->
- <!-- configure Jasper. If not present, the default -->
- <!-- EmbeddedServletOptions will be used. -->
- <!-- -->
- <!-- errorOnUseBeanInvalidClassAttribute -->
- <!-- Should Jasper issue an error when the value of -->
- <!-- the class attribute in an useBean action is -->
- <!-- not a valid bean class? [true] -->
- <!-- -->
- <!-- fork Tell Ant to fork compiles of JSP pages so that -->
- <!-- a separate JVM is used for JSP page compiles -->
- <!-- from the one Tomcat is running in. [true] -->
- <!-- -->
- <!-- genStrAsCharArray Should text strings be generated as char -->
- <!-- arrays, to improve performance in some cases? -->
- <!-- [false] -->
- <!-- -->
- <!-- ieClassId The class-id value to be sent to Internet -->
- <!-- Explorer when using <jsp:plugin> tags. -->
- <!-- [clsid:8AD9C840-044E-11D1-B3E9-00805F499D93] -->
- <!-- -->
- <!-- javaEncoding Java file encoding to use for generating java -->
- <!-- source files. [UTF8] -->
- <!-- -->
- <!-- keepgenerated Should we keep the generated Java source code -->
- <!-- for each page instead of deleting it? [true] -->
- <!-- -->
- <!-- mappedfile Should we generate static content with one -->
- <!-- print statement per input line, to ease -->
- <!-- debugging? [true] -->
- <!-- -->
- <!-- modificationTestInterval -->
- <!-- Causes a JSP (and its dependent files) to not -->
- <!-- be checked for modification during the -->
- <!-- specified time interval (in seconds) from the -->
- <!-- last time the JSP was checked for -->
- <!-- modification. A value of 0 will cause the JSP -->
- <!-- to be checked on every access. -->
- <!-- Used in development mode only. [4] -->
- <!-- -->
- <!-- scratchdir What scratch directory should we use when -->
- <!-- compiling JSP pages? [default work directory -->
- <!-- for the current web application] -->
- <!-- -->
- <!-- suppressSmap Should the generation of SMAP info for JSR45 -->
- <!-- debugging be suppressed? [false] -->
- <!-- -->
- <!-- trimSpaces Should white spaces in template text between -->
- <!-- actions or directives be trimmed? [false] -->
- <!-- -->
- <!-- xpoweredBy Determines whether X-Powered-By response -->
- <!-- header is added by generated servlet [false] -->
- <!-- -->
- <!-- If you wish to use Jikes to compile JSP pages: -->
- <!-- Please see the "Using Jikes" section of the Jasper-HowTo -->
- <!-- page in the Tomcat documentation. -->
-
- <servlet>
- <servlet-name>jsp</servlet-name>
- <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
- <init-param>
- <param-name>fork</param-name>
- <param-value>false</param-value>
- </init-param>
- <init-param>
- <param-name>xpoweredBy</param-name>
- <param-value>false</param-value>
- </init-param>
- <load-on-startup>3</load-on-startup>
- </servlet>
-
-
- <!-- NOTE: An SSI Filter is also available as an alternative SSI -->
- <!-- implementation. Use either the Servlet or the Filter but NOT both. -->
- <!-- -->
- <!-- Server Side Includes processing servlet, which processes SSI -->
- <!-- directives in HTML pages consistent with similar support in web -->
- <!-- servers like Apache. Traditionally, this servlet is mapped to the -->
- <!-- URL pattern "*.shtml". This servlet supports the following -->
- <!-- initialization parameters (default values are in square brackets): -->
- <!-- -->
- <!-- buffered Should output from this servlet be buffered? -->
- <!-- (0=false, 1=true) [0] -->
- <!-- -->
- <!-- debug Debugging detail level for messages logged -->
- <!-- by this servlet. [0] -->
- <!-- -->
- <!-- expires The number of seconds before a page with SSI -->
- <!-- directives will expire. [No default] -->
- <!-- -->
- <!-- isVirtualWebappRelative -->
- <!-- Should "virtual" paths be interpreted as -->
- <!-- relative to the context root, instead of -->
- <!-- the server root? (0=false, 1=true) [0] -->
- <!-- -->
- <!-- inputEncoding The encoding to assume for SSI resources if -->
- <!-- one is not available from the resource. -->
- <!-- [Platform default] -->
- <!-- -->
- <!-- outputEncoding The encoding to use for the page that results -->
- <!-- from the SSI processing. [UTF-8] -->
-
-<!--
- <servlet>
- <servlet-name>ssi</servlet-name>
- <servlet-class>
- org.apache.catalina.ssi.SSIServlet
- </servlet-class>
- <init-param>
- <param-name>buffered</param-name>
- <param-value>1</param-value>
- </init-param>
- <init-param>
- <param-name>debug</param-name>
- <param-value>0</param-value>
- </init-param>
- <init-param>
- <param-name>expires</param-name>
- <param-value>666</param-value>
- </init-param>
- <init-param>
- <param-name>isVirtualWebappRelative</param-name>
- <param-value>0</param-value>
- </init-param>
- <load-on-startup>4</load-on-startup>
- </servlet>
--->
-
-
- <!-- Common Gateway Includes (CGI) processing servlet, which supports -->
- <!-- execution of external applications that conform to the CGI spec -->
- <!-- requirements. Typically, this servlet is mapped to the URL pattern -->
- <!-- "/cgi-bin/*", which means that any CGI applications that are -->
- <!-- executed must be present within the web application. This servlet -->
- <!-- supports the following initialization parameters (default values -->
- <!-- are in square brackets): -->
- <!-- -->
- <!-- cgiPathPrefix The CGI search path will start at -->
- <!-- webAppRootDir + File.separator + this prefix. -->
- <!-- [WEB-INF/cgi] -->
- <!-- -->
- <!-- debug Debugging detail level for messages logged -->
- <!-- by this servlet. [0] -->
- <!-- -->
- <!-- executable Name of the executable used to run the -->
- <!-- script. [perl] -->
- <!-- -->
- <!-- parameterEncoding Name of parameter encoding to be used with -->
- <!-- CGI servlet. -->
- <!-- [System.getProperty("file.encoding","UTF-8")] -->
- <!-- -->
- <!-- passShellEnvironment Should the shell environment variables (if -->
- <!-- any) be passed to the CGI script? [false] -->
- <!-- -->
- <!-- stderrTimeout The time (in milliseconds) to wait for the -->
- <!-- reading of stderr to complete before -->
- <!-- terminating the CGI process. [2000] -->
-
-<!--
- <servlet>
- <servlet-name>cgi</servlet-name>
- <servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class>
- <init-param>
- <param-name>debug</param-name>
- <param-value>0</param-value>
- </init-param>
- <init-param>
- <param-name>cgiPathPrefix</param-name>
- <param-value>WEB-INF/cgi</param-value>
- </init-param>
- <load-on-startup>5</load-on-startup>
- </servlet>
--->
-
-
- <!-- ================ Built In Servlet Mappings ========================= -->
-
-
- <!-- The servlet mappings for the built in servlets defined above. Note -->
- <!-- that, by default, the CGI and SSI servlets are *not* mapped. You -->
- <!-- must uncomment these mappings (or add them to your application's own -->
- <!-- web.xml deployment descriptor) to enable these services -->
-
- <!-- The mapping for the default servlet -->
- <servlet-mapping>
- <servlet-name>default</servlet-name>
- <url-pattern>/</url-pattern>
- </servlet-mapping>
-
- <!-- The mapping for the deprecated invoker servlet -->
-<!--
- <servlet-mapping>
- <servlet-name>invoker</servlet-name>
- <url-pattern>/servlet/*</url-pattern>
- </servlet-mapping>
--->
-
- <!-- The mapping for the JSP servlet -->
- <servlet-mapping>
- <servlet-name>jsp</servlet-name>
- <url-pattern>*.jsp</url-pattern>
- </servlet-mapping>
-
- <servlet-mapping>
- <servlet-name>jsp</servlet-name>
- <url-pattern>*.jspx</url-pattern>
- </servlet-mapping>
-
- <!-- The mapping for the SSI servlet -->
-<!--
- <servlet-mapping>
- <servlet-name>ssi</servlet-name>
- <url-pattern>*.shtml</url-pattern>
- </servlet-mapping>
--->
-
- <!-- The mapping for the CGI Gateway servlet -->
-
-<!--
- <servlet-mapping>
- <servlet-name>cgi</servlet-name>
- <url-pattern>/cgi-bin/*</url-pattern>
- </servlet-mapping>
--->
-
-
- <!-- ================== Built In Filter Definitions ===================== -->
-
- <!-- NOTE: An SSI Servlet is also available as an alternative SSI -->
- <!-- implementation. Use either the Servlet or the Filter but NOT both. -->
- <!-- -->
- <!-- Server Side Includes processing filter, which processes SSI -->
- <!-- directives in HTML pages consistent with similar support in web -->
- <!-- servers like Apache. Traditionally, this filter is mapped to the -->
- <!-- URL pattern "*.shtml", though it can be mapped to "*" as it will -->
- <!-- selectively enable/disable SSI processing based on mime types. For -->
- <!-- this to work you will need to uncomment the .shtml mime type -->
- <!-- definition towards the bottom of this file. -->
- <!-- The contentType init param allows you to apply SSI processing to JSP -->
- <!-- pages, javascript, or any other content you wish. This filter -->
- <!-- supports the following initialization parameters (default values are -->
- <!-- in square brackets): -->
- <!-- -->
- <!-- contentType A regex pattern that must be matched before -->
- <!-- SSI processing is applied. -->
- <!-- [text/x-server-parsed-html(;.*)?] -->
- <!-- -->
- <!-- debug Debugging detail level for messages logged -->
- <!-- by this servlet. [0] -->
- <!-- -->
- <!-- expires The number of seconds before a page with SSI -->
- <!-- directives will expire. [No default] -->
- <!-- -->
- <!-- isVirtualWebappRelative -->
- <!-- Should "virtual" paths be interpreted as -->
- <!-- relative to the context root, instead of -->
- <!-- the server root? (0=false, 1=true) [0] -->
-
-<!--
- <filter>
- <filter-name>ssi</filter-name>
- <filter-class>
- org.apache.catalina.ssi.SSIFilter
- </filter-class>
- <init-param>
- <param-name>contentType</param-name>
- <param-value>text/x-server-parsed-html(;.*)?</param-value>
- </init-param>
- <init-param>
- <param-name>debug</param-name>
- <param-value>0</param-value>
- </init-param>
- <init-param>
- <param-name>expires</param-name>
- <param-value>666</param-value>
- </init-param>
- <init-param>
- <param-name>isVirtualWebappRelative</param-name>
- <param-value>0</param-value>
- </init-param>
- </filter>
--->
-
-
- <!-- ==================== Built In Filter Mappings ====================== -->
-
- <!-- The mapping for the SSI Filter -->
-<!--
- <filter-mapping>
- <filter-name>ssi</filter-name>
- <url-pattern>*.shtml</url-pattern>
- </filter-mapping>
--->
-
-
- <!-- ==================== Default Session Configuration ================= -->
- <!-- You can set the default session timeout (in minutes) for all newly -->
- <!-- created sessions by modifying the value below. -->
-
- <session-config>
- <session-timeout>30</session-timeout>
- </session-config>
-
-
- <!-- ===================== Default MIME Type Mappings =================== -->
- <!-- When serving static resources, Tomcat will automatically generate -->
- <!-- a "Content-Type" header based on the resource's filename extension, -->
- <!-- based on these mappings. Additional mappings can be added here (to -->
- <!-- apply to all web applications), or in your own application's web.xml -->
- <!-- deployment descriptor. -->
-
- <mime-mapping>
- <extension>abs</extension>
- <mime-type>audio/x-mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ai</extension>
- <mime-type>application/postscript</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>aif</extension>
- <mime-type>audio/x-aiff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>aifc</extension>
- <mime-type>audio/x-aiff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>aiff</extension>
- <mime-type>audio/x-aiff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>aim</extension>
- <mime-type>application/x-aim</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>art</extension>
- <mime-type>image/x-jg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>asf</extension>
- <mime-type>video/x-ms-asf</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>asx</extension>
- <mime-type>video/x-ms-asf</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>au</extension>
- <mime-type>audio/basic</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>avi</extension>
- <mime-type>video/x-msvideo</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>avx</extension>
- <mime-type>video/x-rad-screenplay</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>bcpio</extension>
- <mime-type>application/x-bcpio</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>bin</extension>
- <mime-type>application/octet-stream</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>bmp</extension>
- <mime-type>image/bmp</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>body</extension>
- <mime-type>text/html</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>cdf</extension>
- <mime-type>application/x-cdf</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>cer</extension>
- <mime-type>application/x-x509-ca-cert</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>class</extension>
- <mime-type>application/java</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>cpio</extension>
- <mime-type>application/x-cpio</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>csh</extension>
- <mime-type>application/x-csh</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>css</extension>
- <mime-type>text/css</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>dib</extension>
- <mime-type>image/bmp</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>doc</extension>
- <mime-type>application/msword</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>dtd</extension>
- <mime-type>application/xml-dtd</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>dv</extension>
- <mime-type>video/x-dv</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>dvi</extension>
- <mime-type>application/x-dvi</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>eps</extension>
- <mime-type>application/postscript</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>etx</extension>
- <mime-type>text/x-setext</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>exe</extension>
- <mime-type>application/octet-stream</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>gif</extension>
- <mime-type>image/gif</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>gtar</extension>
- <mime-type>application/x-gtar</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>gz</extension>
- <mime-type>application/x-gzip</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>hdf</extension>
- <mime-type>application/x-hdf</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>hqx</extension>
- <mime-type>application/mac-binhex40</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>htc</extension>
- <mime-type>text/x-component</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>htm</extension>
- <mime-type>text/html</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>html</extension>
- <mime-type>text/html</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>hqx</extension>
- <mime-type>application/mac-binhex40</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ief</extension>
- <mime-type>image/ief</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jad</extension>
- <mime-type>text/vnd.sun.j2me.app-descriptor</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jar</extension>
- <mime-type>application/java-archive</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>java</extension>
- <mime-type>text/plain</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jnlp</extension>
- <mime-type>application/x-java-jnlp-file</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jpe</extension>
- <mime-type>image/jpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jpeg</extension>
- <mime-type>image/jpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jpg</extension>
- <mime-type>image/jpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>js</extension>
- <mime-type>text/javascript</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jsf</extension>
- <mime-type>text/plain</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jspf</extension>
- <mime-type>text/plain</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>kar</extension>
- <mime-type>audio/x-midi</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>latex</extension>
- <mime-type>application/x-latex</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>m3u</extension>
- <mime-type>audio/x-mpegurl</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mac</extension>
- <mime-type>image/x-macpaint</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>man</extension>
- <mime-type>application/x-troff-man</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mathml</extension>
- <mime-type>application/mathml+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>me</extension>
- <mime-type>application/x-troff-me</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mid</extension>
- <mime-type>audio/x-midi</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>midi</extension>
- <mime-type>audio/x-midi</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mif</extension>
- <mime-type>application/x-mif</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mov</extension>
- <mime-type>video/quicktime</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>movie</extension>
- <mime-type>video/x-sgi-movie</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mp1</extension>
- <mime-type>audio/x-mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mp2</extension>
- <mime-type>audio/x-mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mp3</extension>
- <mime-type>audio/x-mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mp4</extension>
- <mime-type>video/mp4</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mpa</extension>
- <mime-type>audio/x-mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mpe</extension>
- <mime-type>video/mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mpeg</extension>
- <mime-type>video/mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mpega</extension>
- <mime-type>audio/x-mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mpg</extension>
- <mime-type>video/mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mpv2</extension>
- <mime-type>video/mpeg2</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ms</extension>
- <mime-type>application/x-wais-source</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>nc</extension>
- <mime-type>application/x-netcdf</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>oda</extension>
- <mime-type>application/oda</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Database -->
- <extension>odb</extension>
- <mime-type>application/vnd.oasis.opendocument.database</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Chart -->
- <extension>odc</extension>
- <mime-type>application/vnd.oasis.opendocument.chart</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Formula -->
- <extension>odf</extension>
- <mime-type>application/vnd.oasis.opendocument.formula</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Drawing -->
- <extension>odg</extension>
- <mime-type>application/vnd.oasis.opendocument.graphics</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Image -->
- <extension>odi</extension>
- <mime-type>application/vnd.oasis.opendocument.image</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Master Document -->
- <extension>odm</extension>
- <mime-type>application/vnd.oasis.opendocument.text-master</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Presentation -->
- <extension>odp</extension>
- <mime-type>application/vnd.oasis.opendocument.presentation</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Spreadsheet -->
- <extension>ods</extension>
- <mime-type>application/vnd.oasis.opendocument.spreadsheet</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Text -->
- <extension>odt</extension>
- <mime-type>application/vnd.oasis.opendocument.text</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ogg</extension>
- <mime-type>application/ogg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Drawing Template -->
- <extension>otg </extension>
- <mime-type>application/vnd.oasis.opendocument.graphics-template</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- HTML Document Template -->
- <extension>oth</extension>
- <mime-type>application/vnd.oasis.opendocument.text-web</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Presentation Template -->
- <extension>otp</extension>
- <mime-type>application/vnd.oasis.opendocument.presentation-template</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Spreadsheet Template -->
- <extension>ots</extension>
- <mime-type>application/vnd.oasis.opendocument.spreadsheet-template </mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- OpenDocument Text Template -->
- <extension>ott</extension>
- <mime-type>application/vnd.oasis.opendocument.text-template</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pbm</extension>
- <mime-type>image/x-portable-bitmap</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pct</extension>
- <mime-type>image/pict</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pdf</extension>
- <mime-type>application/pdf</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pgm</extension>
- <mime-type>image/x-portable-graymap</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pic</extension>
- <mime-type>image/pict</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pict</extension>
- <mime-type>image/pict</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pls</extension>
- <mime-type>audio/x-scpls</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>png</extension>
- <mime-type>image/png</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pnm</extension>
- <mime-type>image/x-portable-anymap</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pnt</extension>
- <mime-type>image/x-macpaint</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ppm</extension>
- <mime-type>image/x-portable-pixmap</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ppt</extension>
- <mime-type>application/vnd.ms-powerpoint</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pps</extension>
- <mime-type>application/vnd.ms-powerpoint</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ps</extension>
- <mime-type>application/postscript</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>psd</extension>
- <mime-type>image/x-photoshop</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>qt</extension>
- <mime-type>video/quicktime</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>qti</extension>
- <mime-type>image/x-quicktime</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>qtif</extension>
- <mime-type>image/x-quicktime</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ras</extension>
- <mime-type>image/x-cmu-raster</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>rdf</extension>
- <mime-type>application/rdf+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>rgb</extension>
- <mime-type>image/x-rgb</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>rm</extension>
- <mime-type>application/vnd.rn-realmedia</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>roff</extension>
- <mime-type>application/x-troff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>rtf</extension>
- <mime-type>application/rtf</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>rtx</extension>
- <mime-type>text/richtext</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>sh</extension>
- <mime-type>application/x-sh</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>shar</extension>
- <mime-type>application/x-shar</mime-type>
- </mime-mapping>
-<!--
- <mime-mapping>
- <extension>shtml</extension>
- <mime-type>text/x-server-parsed-html</mime-type>
- </mime-mapping>
--->
- <mime-mapping>
- <extension>smf</extension>
- <mime-type>audio/x-midi</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>sit</extension>
- <mime-type>application/x-stuffit</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>snd</extension>
- <mime-type>audio/basic</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>src</extension>
- <mime-type>application/x-wais-source</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>sv4cpio</extension>
- <mime-type>application/x-sv4cpio</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>sv4crc</extension>
- <mime-type>application/x-sv4crc</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>svg</extension>
- <mime-type>image/svg+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>svgz</extension>
- <mime-type>image/svg+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>swf</extension>
- <mime-type>application/x-shockwave-flash</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>t</extension>
- <mime-type>application/x-troff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>tar</extension>
- <mime-type>application/x-tar</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>tcl</extension>
- <mime-type>application/x-tcl</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>tex</extension>
- <mime-type>application/x-tex</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>texi</extension>
- <mime-type>application/x-texinfo</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>texinfo</extension>
- <mime-type>application/x-texinfo</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>tif</extension>
- <mime-type>image/tiff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>tiff</extension>
- <mime-type>image/tiff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>tr</extension>
- <mime-type>application/x-troff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>tsv</extension>
- <mime-type>text/tab-separated-values</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>txt</extension>
- <mime-type>text/plain</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ulw</extension>
- <mime-type>audio/basic</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ustar</extension>
- <mime-type>application/x-ustar</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>vxml</extension>
- <mime-type>application/voicexml+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xbm</extension>
- <mime-type>image/x-xbitmap</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xht</extension>
- <mime-type>application/xhtml+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xhtml</extension>
- <mime-type>application/xhtml+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xls</extension>
- <mime-type>application/vnd.ms-excel</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xml</extension>
- <mime-type>application/xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xpm</extension>
- <mime-type>image/x-xpixmap</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xsl</extension>
- <mime-type>application/xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xslt</extension>
- <mime-type>application/xslt+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xul</extension>
- <mime-type>application/vnd.mozilla.xul+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xwd</extension>
- <mime-type>image/x-xwindowdump</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>vsd</extension>
- <mime-type>application/x-visio</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>wav</extension>
- <mime-type>audio/x-wav</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- Wireless Bitmap -->
- <extension>wbmp</extension>
- <mime-type>image/vnd.wap.wbmp</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- WML Source -->
- <extension>wml</extension>
- <mime-type>text/vnd.wap.wml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- Compiled WML -->
- <extension>wmlc</extension>
- <mime-type>application/vnd.wap.wmlc</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- WML Script Source -->
- <extension>wmls</extension>
- <mime-type>text/vnd.wap.wmlscript</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- Compiled WML Script -->
- <extension>wmlscriptc</extension>
- <mime-type>application/vnd.wap.wmlscriptc</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>wmv</extension>
- <mime-type>video/x-ms-wmv</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>wrl</extension>
- <mime-type>x-world/x-vrml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>wspolicy</extension>
- <mime-type>application/wspolicy+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>Z</extension>
- <mime-type>application/x-compress</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>z</extension>
- <mime-type>application/x-compress</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>zip</extension>
- <mime-type>application/zip</mime-type>
- </mime-mapping>
-
- <!-- ==================== Default Welcome File List ===================== -->
- <!-- When a request URI refers to a directory, the default servlet looks -->
- <!-- for a "welcome file" within that directory and, if present, -->
- <!-- to the corresponding resource URI for display. If no welcome file -->
- <!-- is present, the default servlet either serves a directory listing, -->
- <!-- or returns a 404 status, depending on how it is configured. -->
- <!-- -->
- <!-- If you define welcome files in your own application's web.xml -->
- <!-- deployment descriptor, that list *replaces* the list configured -->
- <!-- here, so be sure that you include any of the default values that -->
- <!-- you wish to include. -->
-
- <welcome-file-list>
- <welcome-file>index.html</welcome-file>
- <welcome-file>index.htm</welcome-file>
- </welcome-file-list>
-
-</web-app>
diff --git a/packaging/debian/init/cloud-management b/packaging/debian/init/cloud-management
index 05c38be54fc..580f683b829 100755
--- a/packaging/debian/init/cloud-management
+++ b/packaging/debian/init/cloud-management
@@ -1,6 +1,6 @@
#!/bin/sh
#
-# /etc/init.d/tomcat6 -- startup script for the Tomcat 6 servlet engine
+# /etc/init.d/cloudstack-management -- startup script for CloudStack
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
@@ -26,17 +26,18 @@
# Should-Stop: $named
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
-# Short-Description: Start Tomcat (CloudStack).
-# Description: Start the Tomcat servlet engine that runs the CloudStack Management Server.
+# Short-Description: Start CloudStack.
+# Description: Start the CloudStack Management Server.
### END INIT INFO
PATH=/bin:/usr/bin:/sbin:/usr/sbin
NAME=cloudstack-management
-DESC="CloudStack-specific Tomcat servlet engine"
+DESC="CloudStack Management Server"
DAEMON=/usr/bin/jsvc
-CATALINA_HOME=/usr/share/cloudstack-management
-DEFAULT=/etc/cloudstack/management/tomcat6.conf
-JVM_TMP=/tmp/$NAME-temp
+DEFAULT=/etc/default/$NAME
+USER="cloud"
+GROUP="cloud"
+CLOUDSTACK_PID="/var/run/$NAME.pid"
# We have to explicitly set the HOME variable to the homedir from the user "cloud"
# This is because various scripts run by the management server read the HOME variable
@@ -47,8 +48,7 @@ if [ `id -u` -ne 0 ]; then
echo "You need root privileges to run this script"
exit 1
fi
-
-# Make sure tomcat is started with system locale
+
if [ -r /etc/default/locale ]; then
. /etc/default/locale
export LANG
@@ -57,12 +57,6 @@ fi
. /lib/lsb/init-functions
. /etc/default/rcS
-
-# The following variables can be overwritten in $DEFAULT
-
-# Run Tomcat 6 as this user ID
-TOMCAT6_USER=tomcat6
-
# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not
# defined in $DEFAULT)
JDK_DIRS="/usr/lib/jvm/java-8-openjdk-amd64 /usr/lib/jvm/java-8-openjdk-i386 /usr/lib/jvm/java-8-oracle /usr/lib/jvm/java-8-openjdk"
@@ -70,63 +64,21 @@ JDK_DIRS="/usr/lib/jvm/java-8-openjdk-amd64 /usr/lib/jvm/java-8-openjdk-i386 /us
# Look for the right JVM to use
for jdir in $JDK_DIRS; do
if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then
- JAVA_HOME="$jdir"
+ JAVA_HOME="$jdir"
fi
done
export JAVA_HOME
-# Directory for per-instance configuration files and webapps
-CATALINA_BASE=/usr/share/cloudstack-management
-
-# Use the Java security manager? (yes/no)
-TOMCAT6_SECURITY=no
-
-# Default Java options
-# Set java.awt.headless=true if JAVA_OPTS is not set so the
-# Xalan XSL transformer can work without X11 display on JDK 1.4+
-# It also looks like the default heap size of 64M is not enough for most cases
-# so the maximum heap size is set to 128M
-if [ -z "$JAVA_OPTS" ]; then
- JAVA_OPTS="-Djava.awt.headless=true -Xmx128M"
-fi
-
-# End of variables that can be overwritten in $DEFAULT
-
# overwrite settings from default file
if [ -f "$DEFAULT" ]; then
. "$DEFAULT"
fi
-if [ ! -f "$CATALINA_HOME/bin/bootstrap.jar" ]; then
- log_failure_msg "$NAME is not installed"
- exit 1
-fi
+JARS=$(ls /usr/share/cloudstack-management/lib/*.jar | tr '\n' ':' | sed s'/.$//')
+CLASSPATH="$JARS:$CLASSPATH"
[ -f "$DAEMON" ] || exit 0
-POLICY_CACHE="$CATALINA_BASE/work/catalina.policy"
-
-JAVA_OPTS="$JAVA_OPTS -Djava.endorsed.dirs=$CATALINA_HOME/endorsed -Dcatalina.base=$CATALINA_BASE -Dcatalina.home=$CATALINA_HOME -Djava.io.tmpdir=$JVM_TMP"
-
-# Set the JSP compiler if set in the tomcat6.default file
-if [ -n "$JSP_COMPILER" ]; then
- JAVA_OPTS="$JAVA_OPTS -Dbuild.compiler=$JSP_COMPILER"
-fi
-
-if [ "$TOMCAT6_SECURITY" = "yes" ]; then
- JAVA_OPTS="$JAVA_OPTS -Djava.security.manager -Djava.security.policy=$POLICY_CACHE"
-fi
-
-# Set juli LogManager if logging.properties is provided
-if [ -r "$CATALINA_BASE"/conf/logging.properties ]; then
- JAVA_OPTS="$JAVA_OPTS "-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager" "-Djava.util.logging.config.file="$CATALINA_BASE/conf/logging.properties"
-fi
-
-# Define other required variables
-CATALINA_PID="/var/run/$NAME.pid"
-BOOTSTRAP_CLASS=org.apache.catalina.startup.Bootstrap
-JSVC_CLASSPATH="/usr/share/java/commons-daemon.jar:$CATALINA_HOME/bin/bootstrap.jar:/etc/cloudstack/management:/usr/share/cloudstack-management/setup"
-
# Look for Java Secure Sockets Extension (JSSE) JARs
if [ -z "${JSSE_HOME}" -a -r "${JAVA_HOME}/jre/lib/jsse.jar" ]; then
JSSE_HOME="${JAVA_HOME}/jre/"
@@ -140,74 +92,36 @@ case "$1" in
exit 1
fi
- if [ ! -d "$CATALINA_BASE/conf" ]; then
- log_failure_msg "invalid CATALINA_BASE: $CATALINA_BASE"
- exit 1
- fi
-
log_daemon_msg "Starting $DESC" "$NAME"
- if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
- --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
- >/dev/null; then
-
- # Regenerate POLICY_CACHE file
- umask 022
- echo "// AUTO-GENERATED FILE from /etc/tomcat6/policy.d/" \
- > "$POLICY_CACHE"
- echo "" >> "$POLICY_CACHE"
- if ls $CATALINA_BASE/conf/policy.d/*.policy > /dev/null 2>&1 ; then
- cat $CATALINA_BASE/conf/policy.d/*.policy \
- >> "$POLICY_CACHE"
- fi
-
- # Remove / recreate JVM_TMP directory
- rm -rf "$JVM_TMP"
- mkdir "$JVM_TMP" || {
- log_failure_msg "could not create JVM temporary directory"
- exit 1
- }
- chown $TOMCAT6_USER "$JVM_TMP"
- cd "$JVM_TMP"
-
+ if start-stop-daemon --test --start --quiet --pidfile "$CLOUDSTACK_PID" \
+ --user $USER --startas "$JAVA_HOME/bin/java"; then
# fix storage issues on nfs mounts
umask 000
- $DAEMON -user "$TOMCAT6_USER" -cp "$JSVC_CLASSPATH" \
- -outfile SYSLOG -errfile SYSLOG \
- -pidfile "$CATALINA_PID" $JAVA_OPTS "$BOOTSTRAP_CLASS"
-
- sleep 5
- if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
- --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
- >/dev/null; then
- log_end_msg 1
- else
- log_end_msg 0
- fi
+ start-stop-daemon --start --quiet --pidfile "$CLOUDSTACK_PID" \
+ --user $USER --group $GROUP --exec $DAEMON -- -user "$USER" -server \
+ -home "$JAVA_HOME" -cp "$CLASSPATH" \
+ -outfile SYSLOG -errfile $LOGDIR/$NAME.err \
+ -pidfile "$CLOUDSTACK_PID" $JAVA_OPTS "$BOOTSTRAP_CLASS"
+ log_end_msg $?
else
- log_progress_msg "(already running)"
+ log_progress_msg "(already running)"
log_end_msg 0
fi
;;
stop)
log_daemon_msg "Stopping $DESC" "$NAME"
- if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
- --user "$TOMCAT6_USER" --startas "$JAVA_HOME/bin/java" \
- >/dev/null; then
- log_progress_msg "(not running)"
- else
- $DAEMON -cp "$JSVC_CLASSPATH" -pidfile "$CATALINA_PID" \
- -stop "$BOOTSTRAP_CLASS"
- fi
- rm -rf "$JVM_TMP"
+ start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile "$CLOUDSTACK_PID"
+ RETVAL="$?"
+ [ "$RETVAL" = 2 ] && return 2
log_end_msg 0
;;
status)
- if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
- --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
+ if start-stop-daemon --test --start --pidfile "$CLOUDSTACK_PID" \
+ --user $USER --startas "$JAVA_HOME/bin/java" \
>/dev/null; then
- if [ -f "$CATALINA_PID" ]; then
+ if [ -f "$CLOUDSTACK_PID" ]; then
log_success_msg "$DESC is not running, but pid file exists."
exit 1
else
@@ -215,25 +129,18 @@ case "$1" in
exit 3
fi
else
- log_success_msg "$DESC is running with pid `cat $CATALINA_PID`"
+ log_success_msg "$DESC is running with pid `cat $CLOUDSTACK_PID`"
fi
;;
restart|force-reload)
- if start-stop-daemon --test --stop --pidfile "$CATALINA_PID" \
- --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
+ if start-stop-daemon --test --stop --pidfile "$CLOUDSTACK_PID" \
+ --user $USER --startas "$JAVA_HOME/bin/java" \
>/dev/null; then
$0 stop
sleep 1
fi
$0 start
;;
- try-restart)
- if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
- --user $TOMCAT6_USER --startas "$JAVA_HOME/bin/java" \
- >/dev/null; then
- $0 start
- fi
- ;;
*)
log_success_msg "Usage: $0 {start|stop|restart|try-restart|force-reload|status}"
exit 1
diff --git a/packaging/debian/replace.properties b/packaging/debian/replace.properties
index e1d28bb9549..258cb844318 100644
--- a/packaging/debian/replace.properties
+++ b/packaging/debian/replace.properties
@@ -32,7 +32,7 @@ APISERVERLOG=/var/log/cloudstack/management/apilog.log
BINDIR=/usr/bin
COMMONLIBDIR=/usr/share/cloudstack-common
CONFIGUREVARS=
-DEPSCLASSPATH=/usr/share/tomcat6/bin/bootstrap.jar:/usr/share/tomcat6/bin/tomcat-juli.jar
+DEPSCLASSPATH=
DOCDIR=
IPALOCATORLOG=/var/log/cloudstack/management/ipallocator.log
JAVADIR=/usr/share/cloudstack-management/webapps/client/WEB-INF/lib
diff --git a/packaging/fedora20/cloud-agent.rc b/packaging/fedora20/cloud-agent.rc
deleted file mode 100755
index 2defa148883..00000000000
--- a/packaging/fedora20/cloud-agent.rc
+++ /dev/null
@@ -1,118 +0,0 @@
-#!/bin/bash
-
-# chkconfig: 35 99 10
-# description: Cloud Agent
-# pidfile: /var/run/cloudstack-agent.pid
-
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# WARNING: if this script is changed, then all other initscripts MUST BE changed to match it as well
-
-. /etc/rc.d/init.d/functions
-
-# set environment variables
-
-SHORTNAME=$(basename $0 | sed -e 's/^[SK][0-9][0-9]//')
-PIDFILE=/var/run/"$SHORTNAME".pid
-LOCKFILE=/var/lock/subsys/"$SHORTNAME"
-LOGDIR=/var/log/cloudstack/agent
-LOGFILE=${LOGDIR}/agent.log
-PROGNAME="Cloud Agent"
-CLASS="com.cloud.agent.AgentShell"
-JSVC=`which jsvc 2>/dev/null`;
-
-# exit if we don't find jsvc
-if [ -z "$JSVC" ]; then
- echo no jsvc found in path;
- exit 1;
-fi
-
-unset OPTIONS
-[ -r /etc/sysconfig/"$SHORTNAME" ] && source /etc/sysconfig/"$SHORTNAME"
-
-# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT)
-JDK_DIRS="/usr/lib/jvm/jre /usr/lib/jvm/java-7-openjdk /usr/lib/jvm/java-7-openjdk-i386 /usr/lib/jvm/java-7-openjdk-amd64 /usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-openjdk-i386 /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-6-sun"
-
-for jdir in $JDK_DIRS; do
- if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then
- JAVA_HOME="$jdir"
- fi
-done
-export JAVA_HOME
-
-ACP=`ls /usr/share/cloudstack-agent/lib/*.jar | tr '\n' ':' | sed s'/.$//'`
-PCP=`ls /usr/share/cloudstack-agent/plugins/*.jar 2>/dev/null | tr '\n' ':' | sed s'/.$//'`
-
-# We need to append the JSVC daemon JAR to the classpath
-# AgentShell implements the JSVC daemon methods
-export CLASSPATH="/usr/share/java/commons-daemon.jar:$ACP:$PCP:/etc/cloudstack/agent:/usr/share/cloudstack-common/scripts"
-
-start() {
- echo -n $"Starting $PROGNAME: "
- if hostname --fqdn >/dev/null 2>&1 ; then
- $JSVC -Xms256m -Xmx2048m -cp "$CLASSPATH" -pidfile "$PIDFILE" \
- -errfile $LOGDIR/cloudstack-agent.err -outfile $LOGDIR/cloudstack-agent.out $CLASS
- RETVAL=$?
- echo
- else
- failure
- echo
- echo The host name does not resolve properly to an IP address. Cannot start "$PROGNAME". > /dev/stderr
- RETVAL=9
- fi
- [ $RETVAL = 0 ] && touch ${LOCKFILE}
- return $RETVAL
-}
-
-stop() {
- echo -n $"Stopping $PROGNAME: "
- $JSVC -pidfile "$PIDFILE" -stop $CLASS
- RETVAL=$?
- echo
- [ $RETVAL = 0 ] && rm -f ${LOCKFILE} ${PIDFILE}
-}
-
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- status)
- status -p ${PIDFILE} $SHORTNAME
- RETVAL=$?
- ;;
- restart)
- stop
- sleep 3
- start
- ;;
- condrestart)
- if status -p ${PIDFILE} $SHORTNAME >&/dev/null; then
- stop
- sleep 3
- start
- fi
- ;;
- *)
- echo $"Usage: $SHORTNAME {start|stop|restart|condrestart|status|help}"
- RETVAL=3
-esac
-
-exit $RETVAL
diff --git a/packaging/fedora20/cloud-ipallocator.rc b/packaging/fedora20/cloud-ipallocator.rc
deleted file mode 100755
index d3eadec8a82..00000000000
--- a/packaging/fedora20/cloud-ipallocator.rc
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/bin/bash
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# chkconfig: 35 99 10
-# description: Cloud Agent
-
-# WARNING: if this script is changed, then all other initscripts MUST BE changed to match it as well
-
-. /etc/rc.d/init.d/functions
-
-# set environment variables
-
-SHORTNAME="$(basename $(readlink -f $0))"
-PIDFILE=/var/run/"$SHORTNAME".pid
-LOCKFILE=/var/lock/subsys/"$SHORTNAME"
-LOGFILE=/var/log/cloudstack/ipallocator/ipallocator.log
-PROGNAME="External IPAllocator"
-
-unset OPTIONS
-[ -r /etc/sysconfig/"$SHORTNAME" ] && source /etc/sysconfig/"$SHORTNAME"
-DAEMONIZE=/usr/bin/cloud-daemonize
-PROG=/usr/bin/cloud-external-ipallocator.py
-OPTIONS=8083
-
-start() {
- echo -n $"Starting $PROGNAME: "
- if hostname --fqdn >/dev/null 2>&1 ; then
- daemon --check=$SHORTNAME --pidfile=${PIDFILE} "$DAEMONIZE" \
- -n "$SHORTNAME" -p "$PIDFILE" -l "$LOGFILE" "$PROG" $OPTIONS
- RETVAL=$?
- echo
- else
- failure
- echo
- echo The host name does not resolve properly to an IP address. Cannot start "$PROGNAME". > /dev/stderr
- RETVAL=9
- fi
- [ $RETVAL = 0 ] && touch ${LOCKFILE}
- return $RETVAL
-}
-
-stop() {
- echo -n $"Stopping $PROGNAME: "
- killproc -p ${PIDFILE} $SHORTNAME # -d 10 $SHORTNAME
- RETVAL=$?
- echo
- [ $RETVAL = 0 ] && rm -f ${LOCKFILE} ${PIDFILE}
-}
-
-
-# See how we were called.
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- status)
- status -p ${PIDFILE} $SHORTNAME
- RETVAL=$?
- ;;
- restart)
- stop
- sleep 3
- start
- ;;
- condrestart)
- if status -p ${PIDFILE} $SHORTNAME >&/dev/null; then
- stop
- sleep 3
- start
- fi
- ;;
- *)
- echo $"Usage: $SHORTNAME {start|stop|restart|condrestart|status|help}"
- RETVAL=3
-esac
-
-exit $RETVAL
-
diff --git a/packaging/fedora20/cloud-management.rc b/packaging/fedora20/cloud-management.rc
deleted file mode 100755
index f5ed7a8048a..00000000000
--- a/packaging/fedora20/cloud-management.rc
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/bin/bash
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-# cloudstack-management This shell script takes care of starting and stopping Tomcat
-#
-# chkconfig: - 80 20
-#
-### BEGIN INIT INFO
-# Provides: tomcat6
-# Required-Start: $network $syslog
-# Required-Stop: $network $syslog
-# Default-Start:
-# Default-Stop:
-# Description: Release implementation for Servlet 2.5 and JSP 2.1
-# Short-Description: start and stop tomcat
-### END INIT INFO
-#
-# - originally written by Henri Gomez, Keith Irwin, and Nicolas Mailhot
-# - heavily rewritten by Deepak Bhole and Jason Corley
-#
-
-if [ -r /etc/rc.d/init.d/functions ]; then
- . /etc/rc.d/init.d/functions
-fi
-if [ -r /lib/lsb/init-functions ]; then
- . /lib/lsb/init-functions
-fi
-
-
-NAME="$(basename $(readlink -f $0))"
-export SERVICE_NAME="$NAME"
-stop() {
- SHUTDOWN_WAIT="30"
- count="0"
- if [ -f /var/run/${NAME}.pid ]; then
- pid=`cat /var/run/${NAME}.pid`
- kill $pid &>/dev/null
- until [ "$(ps --pid $pid | grep -c $pid)" -eq "0" ] || \
- [ "$count" -gt "$SHUTDOWN_WAIT" ]
- do
- sleep 1
- let count="${count}+1"
- done
- if [ "$(ps --pid $pid | grep -c $pid)" -eq "0" ]; then
- log_success_msg "Stopping ${NAME}:"
- rm -f /var/run/${NAME}.pid
- rm -f /var/lock/subsys/${NAME}
- else
- log_failure_msg "Stopping ${NAME}:"
- fi
- else
- echo "Cannot find PID file of ${NAME}"
- log_failure_msg "Stopping ${NAME}:"
- fi
-}
-
-set_ulimit() {
- fd_limit=`ulimit -n`
- if [ "$fd_limit" != "4096" ]; then
- user=`whoami`
- if [ $user == "root" ]; then
- ulimit -n 4096
- fi
- fi
-}
-
-handle_pid_file() {
- if [ "$1" -ne 0 ] && [ "$1" -ne 3 ]; then
- echo "The pid file locates at /var/run/${NAME}.pid and lock file at /var/lock/subsys/${NAME}.
- Starting ${NAME} will take care of them or you can manually clean up."
- fi
-}
-
-start() {
- readpath=$(readlink -f $0)
- source `dirname $readpath`/tomcat.sh
-}
-
-# See how we were called.
-case "$1" in
- status)
- status ${NAME}
- RETVAL=$?
- handle_pid_file $RETVAL
- ;;
- stop)
- stop
- ;;
- restart)
- stop
- set start
- set_ulimit
- start
- ;;
- *)
- set_ulimit
- start
-esac
-
-exit $RETVAL
diff --git a/packaging/fedora20/cloud-management.sysconfig b/packaging/fedora20/cloud-management.sysconfig
deleted file mode 100644
index cbc8b8b36c1..00000000000
--- a/packaging/fedora20/cloud-management.sysconfig
+++ /dev/null
@@ -1,23 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# This file is loaded in /etc/init.d/vmopsmanagement
-# ATM we only do two things here:
-
-dummy=1 ; export TOMCAT_CFG=/etc/cloudstack/management/tomcat6.conf ; . /etc/cloudstack/management/tomcat6.conf
-#--------------------------
-
diff --git a/packaging/fedora20/cloud-usage.rc b/packaging/fedora20/cloud-usage.rc
deleted file mode 100755
index 774113745d7..00000000000
--- a/packaging/fedora20/cloud-usage.rc
+++ /dev/null
@@ -1,156 +0,0 @@
-#!/bin/bash
-
-### BEGIN INIT INFO
-# Provides: cloudstack-usage
-# Required-Start: $network $local_fs
-# Required-Stop: $network $local_fs
-# Default-Start: 3 4 5
-# Default-Stop: 0 1 2 6
-# Short-Description: Start/stop Apache CloudStack Usage Monitor
-# Description: This scripts Starts/Stops the Apache CloudStack Usage Monitor
-## The CloudStack Usage Monitor is a part of the Apache CloudStack project and is used
-## for storing usage statistics from instances.
-## JSVC (Java daemonizing) is used for starting and stopping the usage monitor.
-### END INIT INFO
-
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-. /etc/rc.d/init.d/functions
-
-SHORTNAME="cloudstack-usage"
-PIDFILE=/var/run/"$SHORTNAME".pid
-LOCKFILE=/var/lock/subsys/"$SHORTNAME"
-LOGDIR=/var/log/cloudstack/usage
-LOGFILE=${LOGDIR}/usage.log
-PROGNAME="CloudStack Usage Monitor"
-CLASS="com.cloud.usage.UsageServer"
-PROG="jsvc"
-DAEMON="/usr/bin/jsvc"
-USER=cloud
-
-unset OPTIONS
-[ -r /etc/sysconfig/default/"$SHORTNAME" ] && source /etc/sysconfig/default/"$SHORTNAME"
-
-setJavaHome() {
- # use $JAVA_HOME if defined
- if [ -n "$JAVA_HOME" ] ; then
- return
- fi
-
- # try java first
- java=$(which java 2>/dev/null || :)
-
- # try javac if java is not found
- if [ -z "$java" ] ; then
- java=$(which javac 2>/dev/null || :)
- fi
-
- if [ -n "$java" ] ; then
- JAVA_HOME=$(dirname $(dirname $(readlink -e $java)))
- export JAVA_HOME
- return
- fi
-
- # didnt find java home. exiting with error
- exit 1
-}
-
-setJavaHome
-
-SCP=""
-DCP=""
-UCP=`ls /usr/share/cloudstack-usage/cloud-usage-*.jar`":"`ls /usr/share/cloudstack-usage/lib/*.jar | tr '\n' ':'`
-JCP="/usr/share/java/commons-daemon.jar":"/usr/share/java/mysql-connector-java.jar"
-
-# We need to append the JSVC daemon and mysql-connector JAR to the classpath
-# AgentShell implements the JSVC daemon methods
-export CLASSPATH="$SCP:$DCP:$UCP:$JCP:/etc/cloudstack/usage"
-
-start() {
- if [ -s "$PIDFILE" ] && kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then
- echo "$PROGNAME apparently already running"
- exit 0
- fi
-
- if hostname --fqdn >/dev/null 2>&1 ; then
- true
- else
- echo "The host name does not resolve properly to an IP address. Cannot start $PROGNAME"
- exit 1
- fi
-
- echo -n "Starting $PROGNAME" "$SHORTNAME"
-
- if daemon --pidfile $PIDFILE $DAEMON -home "$JAVA_HOME" -cp "$CLASSPATH" -pidfile "$PIDFILE" -user "$USER" \
- -errfile $LOGDIR/cloudstack-usage.err -outfile $LOGDIR/cloudstack-usage.out -Dpid=$$ $CLASS
- RETVAL=$?
- then
- rc=0
- sleep 1
- if ! kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then
- failure
- rc=1
- fi
- else
- rc=1
- fi
-
- if [ $rc -eq 0 ]; then
- success
- else
- failure
- rm -f "$PIDFILE"
- fi
- echo
-}
-
-stop() {
- echo -n "Stopping $PROGNAME" "$SHORTNAME"
- killproc -p $PIDFILE $DAEMON
- if [ "$?" -eq 0 ]; then
- success
- else
- failure
- fi
- rm -f "$PIDFILE"
- echo
-}
-
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- status)
- status -p $PIDFILE $SHORTNAME
- RETVAL=$?
- ;;
- restart | force-reload)
- stop
- sleep 3
- start
- ;;
- *)
- echo "Usage: $0 {start|stop|restart|force-reload|status}"
- RETVAL=3
-esac
-
-exit $RETVAL
-
diff --git a/packaging/fedora20/cloud.spec b/packaging/fedora20/cloud.spec
deleted file mode 100644
index 546e439da2b..00000000000
--- a/packaging/fedora20/cloud.spec
+++ /dev/null
@@ -1,655 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-%define __os_install_post %{nil}
-%global debug_package %{nil}
-
-# DISABLE the post-percentinstall java repacking and line number stripping
-# we need to find a way to just disable the java repacking and line number stripping, but not the autodeps
-
-Name: cloudstack
-Summary: CloudStack IaaS Platform
-#http://fedoraproject.org/wiki/PackageNamingGuidelines#Pre-Release_packages
-%if "%{?_prerelease}" != ""
-%define _maventag %{_ver}-SNAPSHOT
-Release: %{_rel}%{dist}
-%else
-%define _maventag %{_ver}
-Release: %{_rel}%{dist}
-%endif
-
-%{!?python_sitearch: %define python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(1))")}
-
-Version: %{_ver}
-License: ASL 2.0
-Vendor: Apache CloudStack <de...@cloudstack.apache.org>
-Packager: Apache CloudStack <de...@cloudstack.apache.org>
-Group: System Environment/Libraries
-# FIXME do groups for every single one of the subpackages
-Source0: %{name}-%{_maventag}.tgz
-BuildRoot: %{_tmppath}/%{name}-%{_maventag}-%{release}-build
-
-BuildRequires: java-1.7.0-openjdk-devel
-BuildRequires: tomcat
-BuildRequires: ws-commons-util
-BuildRequires: jpackage-utils
-BuildRequires: gcc
-BuildRequires: glibc-devel
-BuildRequires: /usr/bin/mkisofs
-BuildRequires: mysql-connector-python
-#BuildRequires: maven => 3.0.0
-
-%description
-CloudStack is a highly-scalable elastic, open source,
-intelligent IaaS cloud implementation.
-
-%package management
-Summary: CloudStack management server UI
-Requires: tomcat
-Requires: java-1.7.0-openjdk
-Requires: python
-Requires: bash
-Requires: bzip2
-Requires: gzip
-Requires: unzip
-Requires: /sbin/mount.nfs
-Requires: openssh-clients
-Requires: nfs-utils
-Requires: wget
-Requires: mysql
-Requires: mysql-connector-java
-Requires: ws-commons-util
-Requires: jpackage-utils
-Requires: sudo
-Requires: /sbin/service
-Requires: /sbin/chkconfig
-Requires: /usr/bin/ssh-keygen
-Requires: mkisofs
-Requires: mysql-connector-python
-Requires: python-paramiko
-Requires: ipmitool
-Requires: %{name}-common = %{_ver}
-Obsoletes: cloud-client < 4.1.0
-Obsoletes: cloud-client-ui < 4.1.0
-Obsoletes: cloud-server < 4.1.0
-Obsoletes: cloud-test < 4.1.0
-Provides: cloud-client
-Group: System Environment/Libraries
-%description management
-The CloudStack management server is the central point of coordination,
-management, and intelligence in CloudStack.
-
-%package common
-Summary: Apache CloudStack common files and scripts
-Requires: python
-Obsoletes: cloud-test < 4.1.0
-Obsoletes: cloud-scripts < 4.1.0
-Obsoletes: cloud-utils < 4.1.0
-Obsoletes: cloud-core < 4.1.0
-Obsoletes: cloud-deps < 4.1.0
-Obsoletes: cloud-python < 4.1.0
-Obsoletes: cloud-setup < 4.1.0
-Obsoletes: cloud-cli < 4.1.0
-Obsoletes: cloud-daemonize < 4.1.0
-Group: System Environment/Libraries
-%description common
-The Apache CloudStack files shared between agent and management server
-
-%package agent
-Summary: CloudStack Agent for KVM hypervisors
-Requires: openssh-clients
-Requires: java-1.7.0-openjdk
-Requires: %{name}-common = %{_ver}
-Requires: libvirt
-Requires: bridge-utils
-Requires: ebtables
-Requires: iptables
-Requires: ethtool
-Requires: vconfig
-Requires: ipset
-Requires: jsvc
-Requires: jakarta-commons-daemon
-Requires: jakarta-commons-daemon-jsvc
-Requires: perl
-Requires: libvirt-python
-Requires: qemu-img
-Requires: qemu-kvm
-Requires: libcgroup-tools
-Requires: net-tools
-Provides: cloud-agent
-Obsoletes: cloud-agent < 4.1.0
-Obsoletes: cloud-agent-libs < 4.1.0
-Obsoletes: cloud-test < 4.1.0
-Group: System Environment/Libraries
-%description agent
-The CloudStack agent for KVM hypervisors
-
-%package baremetal-agent
-Summary: CloudStack baremetal agent
-Requires: tftp-server
-Requires: xinetd
-Requires: syslinux
-Requires: chkconfig
-Requires: dhcp
-Requires: httpd
-Group: System Environment/Libraries
-%description baremetal-agent
-The CloudStack baremetal agent
-
-%package usage
-Summary: CloudStack Usage calculation server
-Requires: java-1.7.0-openjdk
-Requires: jsvc
-Requires: jakarta-commons-daemon
-Requires: jakarta-commons-daemon-jsvc
-Group: System Environment/Libraries
-Obsoletes: cloud-usage < 4.1.0
-Provides: cloud-usage
-%description usage
-The CloudStack usage calculation service
-
-%package cli
-Summary: Apache CloudStack CLI
-Provides: python-cloudmonkey
-Provides: python-marvin
-Group: System Environment/Libraries
-%description cli
-Apache CloudStack command line interface
-
-%if "%{_ossnoss}" == "noredist"
-%package mysql-ha
-Summary: Apache CloudStack Balancing Strategy for MySQL
-Requires: mysql-connector-java
-Requires: tomcat
-Group: System Environmnet/Libraries
-%description mysql-ha
-Apache CloudStack Balancing Strategy for MySQL
-
-%endif
-
-%prep
-echo Doing CloudStack build
-
-%setup -q -n %{name}-%{_maventag}
-
-%build
-
-cp packaging/centos63/replace.properties build/replace.properties
-echo VERSION=%{_maventag} >> build/replace.properties
-echo PACKAGE=%{name} >> build/replace.properties
-touch build/gitrev.txt
-echo $(git rev-parse HEAD) > build/gitrev.txt
-
-if [ "%{_ossnoss}" == "NOREDIST" -o "%{_ossnoss}" == "noredist" ] ; then
- echo "Executing mvn packaging with non-redistributable libraries"
- if [ "%{_sim}" == "SIMULATOR" -o "%{_sim}" == "simulator" ] ; then
- echo "Executing mvn noredist packaging with simulator ..."
- mvn -Psystemvm -Dnoredist -Dsimulator clean package
- else
- echo "Executing mvn noredist packaging without simulator..."
- mvn -Psystemvm -Dnoredist clean package
- fi
-else
- if [ "%{_sim}" == "SIMULATOR" -o "%{_sim}" == "simulator" ] ; then
- echo "Executing mvn default packaging simulator ..."
- mvn -Psystemvm -Dsimulator clean package
- else
- echo "Executing mvn default packaging without simulator ..."
- mvn -Psystemvm clean package
- fi
-fi
-
-%install
-[ ${RPM_BUILD_ROOT} != "/" ] && rm -rf ${RPM_BUILD_ROOT}
-# Common directories
-mkdir -p ${RPM_BUILD_ROOT}%{_bindir}
-mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/agent
-mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/ipallocator
-mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/cache/%{name}/management/work
-mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/cache/%{name}/management/temp
-mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/%{name}/mnt
-mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/%{name}/management
-mkdir -p ${RPM_BUILD_ROOT}%{_initrddir}
-mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig
-mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/profile.d
-
-# Common
-mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts
-mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms
-mkdir -p ${RPM_BUILD_ROOT}%{python_sitearch}/
-mkdir -p ${RPM_BUILD_ROOT}%/usr/bin
-cp -r scripts/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts
-install -D systemvm/dist/systemvm.iso ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/systemvm.iso
-install python/lib/cloud_utils.py ${RPM_BUILD_ROOT}%{python_sitearch}/cloud_utils.py
-cp -r python/lib/cloudutils ${RPM_BUILD_ROOT}%{python_sitearch}/
-python -m py_compile ${RPM_BUILD_ROOT}%{python_sitearch}/cloud_utils.py
-python -m compileall ${RPM_BUILD_ROOT}%{python_sitearch}/cloudutils
-cp build/gitrev.txt ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts
-cp packaging/centos63/cloudstack-sccs ${RPM_BUILD_ROOT}/usr/bin
-
-mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts/network/cisco
-cp -r plugins/network-elements/cisco-vnmc/scripts/network/cisco/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts/network/cisco
-
-# Management
-mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/
-mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client
-mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/setup
-mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/management
-mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management
-
-# Specific for tomcat
-mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/Catalina/localhost/client
-ln -sf /usr/share/tomcat/bin ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/bin
-ln -sf /etc/%{name}/management ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/conf
-ln -sf /usr/share/tomcat/lib ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/lib
-ln -sf /var/log/%{name}/management ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/logs
-ln -sf /var/cache/%{name}/management/temp ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/temp
-ln -sf /var/cache/%{name}/management/work ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/work
-
-/bin/touch ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/management/catalina.out
-
-install -D client/target/utilities/bin/cloud-migrate-databases ${RPM_BUILD_ROOT}%{_bindir}/%{name}-migrate-databases
-install -D client/target/utilities/bin/cloud-set-guest-password ${RPM_BUILD_ROOT}%{_bindir}/%{name}-set-guest-password
-install -D client/target/utilities/bin/cloud-set-guest-sshkey ${RPM_BUILD_ROOT}%{_bindir}/%{name}-set-guest-sshkey
-install -D client/target/utilities/bin/cloud-setup-databases ${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-databases
-install -D client/target/utilities/bin/cloud-setup-encryption ${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-encryption
-install -D client/target/utilities/bin/cloud-setup-management ${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-management
-install -D client/target/utilities/bin/cloud-setup-baremetal ${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-baremetal
-install -D client/target/utilities/bin/cloud-sysvmadm ${RPM_BUILD_ROOT}%{_bindir}/%{name}-sysvmadm
-install -D client/target/utilities/bin/cloud-update-xenserver-licenses ${RPM_BUILD_ROOT}%{_bindir}/%{name}-update-xenserver-licenses
-
-cp -r client/target/utilities/scripts/db/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/setup
-cp -r client/target/cloud-client-ui-%{_maventag}/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client
-
-# Don't package the scripts in the management webapp
-rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/scripts
-rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/vms
-
-for name in db.properties log4j-cloud.xml tomcat6-nonssl.conf tomcat6-ssl.conf server-ssl.xml server-nonssl.xml \
- catalina.policy catalina.properties classpath.conf tomcat-users.xml web.xml environment.properties java.security.ciphers ; do
- mv ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/$name \
- ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/$name
-done
-
-ln -s %{_sysconfdir}/%{name}/management/log4j-cloud.xml \
- ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/log4j-cloud.xml
-
-mv ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/context.xml \
- ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/Catalina/localhost/client
-
-install python/bindir/cloud-external-ipallocator.py ${RPM_BUILD_ROOT}%{_bindir}/%{name}-external-ipallocator.py
-install -D client/target/pythonlibs/jasypt-1.9.2.jar ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/lib/jasypt-1.9.2.jar
-
-install -D packaging/centos63/cloud-ipallocator.rc ${RPM_BUILD_ROOT}%{_initrddir}/%{name}-ipallocator
-install -D packaging/centos63/cloud-management.rc ${RPM_BUILD_ROOT}%{_initrddir}/%{name}-management
-install -D packaging/centos63/cloud-management.sysconfig ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig/%{name}-management
-install -D packaging/centos63/tomcat.sh ${RPM_BUILD_ROOT}%{_initrddir}/tomcat.sh
-install -D server/target/conf/cloudstack-catalina.logrotate ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/%{name}-catalina
-
-chmod 440 ${RPM_BUILD_ROOT}%{_sysconfdir}/sudoers.d/%{name}-management
-chmod 770 ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/Catalina
-chmod 770 ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/Catalina/localhost
-chmod 770 ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/Catalina/localhost/client
-chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/%{name}/mnt
-chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/%{name}/management
-chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/cache/%{name}/management/work
-chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/cache/%{name}/management/temp
-chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/management
-chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/agent
-
-# KVM Agent
-mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/agent
-mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/agent
-mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-agent/lib
-mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-agent/plugins
-install -D packaging/centos63/cloud-agent.rc ${RPM_BUILD_ROOT}%{_sysconfdir}/init.d/%{name}-agent
-install -D agent/target/transformed/agent.properties ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/agent/agent.properties
-install -D agent/target/transformed/environment.properties ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/agent/environment.properties
-install -D agent/target/transformed/log4j-cloud.xml ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/agent/log4j-cloud.xml
-install -D agent/target/transformed/cloud-setup-agent ${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-agent
-install -D agent/target/transformed/cloudstack-agent-upgrade ${RPM_BUILD_ROOT}%{_bindir}/%{name}-agent-upgrade
-install -D agent/target/transformed/libvirtqemuhook ${RPM_BUILD_ROOT}%{_datadir}/%{name}-agent/lib/libvirtqemuhook
-install -D agent/target/transformed/cloud-ssh ${RPM_BUILD_ROOT}%{_bindir}/%{name}-ssh
-install -D agent/target/transformed/cloudstack-agent-profile.sh ${RPM_BUILD_ROOT}%{_sysconfdir}/profile.d/%{name}-agent-profile.sh
-install -D agent/target/transformed/cloudstack-agent.logrotate ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/%{name}-agent
-install -D plugins/hypervisors/kvm/target/cloud-plugin-hypervisor-kvm-%{_maventag}.jar ${RPM_BUILD_ROOT}%{_datadir}/%name-agent/lib/cloud-plugin-hypervisor-kvm-%{_maventag}.jar
-cp plugins/hypervisors/kvm/target/dependencies/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-agent/lib
-
-# Usage server
-mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/usage
-mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-usage/lib
-install -D usage/target/cloud-usage-%{_maventag}.jar ${RPM_BUILD_ROOT}%{_datadir}/%{name}-usage/cloud-usage-%{_maventag}.jar
-install -D usage/target/transformed/db.properties ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/usage/db.properties
-install -D usage/target/transformed/log4j-cloud_usage.xml ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/usage/log4j-cloud.xml
-cp usage/target/dependencies/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-usage/lib/
-install -D packaging/centos63/cloud-usage.rc ${RPM_BUILD_ROOT}/%{_sysconfdir}/init.d/%{name}-usage
-mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/usage/
-
-# CLI
-cp -r cloud-cli/cloudtool ${RPM_BUILD_ROOT}%{python_sitearch}/
-install cloud-cli/cloudapis/cloud.py ${RPM_BUILD_ROOT}%{python_sitearch}/cloudapis.py
-
-# MYSQL HA
-if [ "x%{_ossnoss}" == "xnoredist" ] ; then
- mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-mysql-ha/lib
- cp -r plugins/database/mysql-ha/target/cloud-plugin-database-mysqlha-%{_maventag}.jar ${RPM_BUILD_ROOT}%{_datadir}/%{name}-mysql-ha/lib
-fi
-
-#License files from whisker
-install -D tools/whisker/NOTICE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-management-%{version}/NOTICE
-install -D tools/whisker/LICENSE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-management-%{version}/LICENSE
-install -D tools/whisker/NOTICE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-common-%{version}/NOTICE
-install -D tools/whisker/LICENSE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-common-%{version}/LICENSE
-install -D tools/whisker/NOTICE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-agent-%{version}/NOTICE
-install -D tools/whisker/LICENSE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-agent-%{version}/LICENSE
-install -D tools/whisker/NOTICE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-usage-%{version}/NOTICE
-install -D tools/whisker/LICENSE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-usage-%{version}/LICENSE
-install -D tools/whisker/NOTICE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-cli-%{version}/NOTICE
-install -D tools/whisker/LICENSE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-cli-%{version}/LICENSE
-if [ "x%{_ossnoss}" == "xnoredist" ] ; then
- install -D tools/whisker/LICENSE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-mysql-ha-%{version}/LICENSE
- install -D tools/whisker/NOTICE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-mysql-ha-%{version}/NOTICE
-fi
-
-%clean
-[ ${RPM_BUILD_ROOT} != "/" ] && rm -rf ${RPM_BUILD_ROOT}
-
-%preun management
-/sbin/service cloudstack-management stop || true
-if [ "$1" == "0" ] ; then
- /sbin/chkconfig --del cloudstack-management > /dev/null 2>&1 || true
- /sbin/service cloudstack-management stop > /dev/null 2>&1 || true
-fi
-
-%pre management
-id cloud > /dev/null 2>&1 || /usr/sbin/useradd -M -c "CloudStack unprivileged user" \
- -r -s /bin/sh -d %{_localstatedir}/cloudstack/management cloud|| true
-
-# set max file descriptors for cloud user to 4096
-sed -i /"cloud hard nofile"/d /etc/security/limits.conf
-sed -i /"cloud soft nofile"/d /etc/security/limits.conf
-echo "cloud hard nofile 4096" >> /etc/security/limits.conf
-echo "cloud soft nofile 4096" >> /etc/security/limits.conf
-rm -rf %{_localstatedir}/cache/cloud
-rm -rf %{_localstatedir}/cache/cloudstack
-# user harcoded here, also hardcoded on wscript
-
-# save old configs if they exist (for upgrade). Otherwise we may lose them
-# when the old packages are erased. There are a lot of properties files here.
-if [ -d "%{_sysconfdir}/cloud" ] ; then
- mv %{_sysconfdir}/cloud %{_sysconfdir}/cloud.rpmsave
-fi
-
-# in case of upgrade to 4.9+ copy commands.properties if not exists in /etc/cloudstack/management/
-if [ "$1" == "2" ] ; then
- if [ -f "%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/commands.properties" ] && [ ! -f "%{_sysconfdir}/%{name}/management/commands.properties" ] ; then
- cp -p %{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/commands.properties %{_sysconfdir}/%{name}/management/commands.properties
- fi
-fi
-
-%post management
-if [ "$1" == "1" ] ; then
- /sbin/chkconfig --add cloudstack-management > /dev/null 2>&1 || true
- /sbin/chkconfig --level 345 cloudstack-management on > /dev/null 2>&1 || true
-fi
-
-if [ ! -f %{_datadir}/cloudstack-common/scripts/vm/hypervisor/xenserver/vhd-util ] ; then
- echo Please download vhd-util from http://download.cloudstack.org/tools/vhd-util and put it in
- echo %{_datadir}/cloudstack-common/scripts/vm/hypervisor/xenserver/
-fi
-
-# change cloud user's home to 4.1+ version if needed. Would do this via 'usermod', but it
-# requires that cloud user not be in use, so RPM could not be installed while management is running
-if getent passwd cloud | grep -q /var/lib/cloud; then
- sed -i 's/\/var\/lib\/cloud\/management/\/var\/cloudstack\/management/g' /etc/passwd
-fi
-
-# if saved configs from upgrade exist, copy them over
-if [ -f "%{_sysconfdir}/cloud.rpmsave/management/db.properties" ]; then
- mv %{_sysconfdir}/%{name}/management/db.properties %{_sysconfdir}/%{name}/management/db.properties.rpmnew
- cp -p %{_sysconfdir}/cloud.rpmsave/management/db.properties %{_sysconfdir}/%{name}/management
- if [ -f "%{_sysconfdir}/cloud.rpmsave/management/key" ]; then
- cp -p %{_sysconfdir}/cloud.rpmsave/management/key %{_sysconfdir}/%{name}/management
- fi
- # make sure we only do this on the first install of this RPM, don't want to overwrite on a reinstall
- mv %{_sysconfdir}/cloud.rpmsave/management/db.properties %{_sysconfdir}/cloud.rpmsave/management/db.properties.rpmsave
-fi
-
-# Choose server.xml and tomcat.conf links based on old config, if exists
-serverxml=%{_sysconfdir}/%{name}/management/server.xml
-oldserverxml=%{_sysconfdir}/cloud.rpmsave/management/server.xml
-if [ -f $oldserverxml ] || [ -L $oldserverxml ]; then
- if stat -c %N $oldserverxml| grep -q server-ssl ; then
- if [ -f $serverxml ] || [ -L $serverxml ]; then rm -f $serverxml; fi
- ln -s %{_sysconfdir}/%{name}/management/server-ssl.xml $serverxml
- echo Please verify the server.xml in saved folder, and make the required changes manually , saved folder available at $oldserverxml
- else
- if [ -f $serverxml ] || [ -L $serverxml ]; then rm -f $serverxml; fi
- ln -s %{_sysconfdir}/%{name}/management/server-nonssl.xml $serverxml
- echo Please verify the server.xml in saved folder, and make the required changes manually , saved folder available at $oldserverxml
-
- fi
-else
- echo "Unable to determine ssl settings for server.xml, please run cloudstack-setup-management manually"
-fi
-
-
-tomcatconf=%{_sysconfdir}/%{name}/management/tomcat6.conf
-oldtomcatconf=%{_sysconfdir}/cloud.rpmsave/management/tomcat6.conf
-if [ -f $oldtomcatconf ] || [ -L $oldtomcatconf ] ; then
- if stat -c %N $oldtomcatconf| grep -q tomcat6-ssl ; then
- if [ -f $tomcatconf ] || [ -L $tomcatconf ]; then rm -f $tomcatconf; fi
- ln -s %{_sysconfdir}/%{name}/management/tomcat6-ssl.conf $tomcatconf
- echo Please verify the tomcat6.conf in saved folder, and make the required changes manually , saved folder available at $oldtomcatconf
- else
- if [ -f $tomcatconf ] || [ -L $tomcatconf ]; then rm -f $tomcatconf; fi
- ln -s %{_sysconfdir}/%{name}/management/tomcat6-nonssl.conf $tomcatconf
- echo Please verify the tomcat6.conf in saved folder, and make the required changes manually , saved folder available at $oldtomcatconf
- fi
-else
- echo "Unable to determine ssl settings for tomcat.conf, please run cloudstack-setup-management manually"
-fi
-
-if [ -f "%{_sysconfdir}/cloud.rpmsave/management/cloud.keystore" ]; then
- cp -p %{_sysconfdir}/cloud.rpmsave/management/cloud.keystore %{_sysconfdir}/%{name}/management/cloudmanagementserver.keystore
- # make sure we only do this on the first install of this RPM, don't want to overwrite on a reinstall
- mv %{_sysconfdir}/cloud.rpmsave/management/cloud.keystore %{_sysconfdir}/cloud.rpmsave/management/cloud.keystore.rpmsave
-fi
-
-%preun agent
-/sbin/service cloudstack-agent stop || true
-if [ "$1" == "0" ] ; then
- /sbin/chkconfig --del cloudstack-agent > /dev/null 2>&1 || true
- /sbin/service cloudstack-agent stop > /dev/null 2>&1 || true
-fi
-
-%pre agent
-
-# save old configs if they exist (for upgrade). Otherwise we may lose them
-# when the old packages are erased. There are a lot of properties files here.
-if [ -d "%{_sysconfdir}/cloud" ] ; then
- mv %{_sysconfdir}/cloud %{_sysconfdir}/cloud.rpmsave
-fi
-
-%post agent
-if [ "$1" == "1" ] ; then
- echo "Running %{_bindir}/%{name}-agent-upgrade to update bridge name for upgrade from CloudStack 4.0.x (and before) to CloudStack 4.1 (and later)"
- %{_bindir}/%{name}-agent-upgrade
- if [ ! -d %{_sysconfdir}/libvirt/hooks ] ; then
- mkdir %{_sysconfdir}/libvirt/hooks
- fi
- cp -a ${RPM_BUILD_ROOT}%{_datadir}/%{name}-agent/lib/libvirtqemuhook %{_sysconfdir}/libvirt/hooks/qemu
- /sbin/service libvirtd restart
- /sbin/chkconfig --add cloudstack-agent > /dev/null 2>&1 || true
- /sbin/chkconfig --level 345 cloudstack-agent on > /dev/null 2>&1 || true
-fi
-
-# if saved configs from upgrade exist, copy them over
-if [ -f "%{_sysconfdir}/cloud.rpmsave/agent/agent.properties" ]; then
- mv %{_sysconfdir}/%{name}/agent/agent.properties %{_sysconfdir}/%{name}/agent/agent.properties.rpmnew
- cp -p %{_sysconfdir}/cloud.rpmsave/agent/agent.properties %{_sysconfdir}/%{name}/agent
- # make sure we only do this on the first install of this RPM, don't want to overwrite on a reinstall
- mv %{_sysconfdir}/cloud.rpmsave/agent/agent.properties %{_sysconfdir}/cloud.rpmsave/agent/agent.properties.rpmsave
-fi
-
-%preun usage
-/sbin/service cloudstack-usage stop || true
-if [ "$1" == "0" ] ; then
- /sbin/chkconfig --del cloudstack-usage > /dev/null 2>&1 || true
- /sbin/service cloudstack-usage stop > /dev/null 2>&1 || true
-fi
-
-%post usage
-if [ -f "%{_sysconfdir}/%{name}/management/db.properties" ]; then
- echo Replacing db.properties with management server db.properties
- rm -f %{_sysconfdir}/%{name}/usage/db.properties
- ln -s %{_sysconfdir}/%{name}/management/db.properties %{_sysconfdir}/%{name}/usage/db.properties
- /sbin/chkconfig --add cloudstack-usage > /dev/null 2>&1 || true
- /sbin/chkconfig --level 345 cloudstack-usage on > /dev/null 2>&1 || true
-fi
-
-if [ -f "%{_sysconfdir}/%{name}/management/key" ]; then
- echo Replacing key with management server key
- rm -f %{_sysconfdir}/%{name}/usage/key
- ln -s %{_sysconfdir}/%{name}/management/key %{_sysconfdir}/%{name}/usage/key
-fi
-
-#No default permission as the permission setup is complex
-%files management
-%defattr(-,root,root,-)
-%dir %attr(0770,root,cloud) %{_sysconfdir}/%{name}/management/Catalina
-%dir %attr(0770,root,cloud) %{_sysconfdir}/%{name}/management/Catalina/localhost
-%dir %attr(0770,root,cloud) %{_sysconfdir}/%{name}/management/Catalina/localhost/client
-%dir %{_datadir}/%{name}-management
-%dir %attr(0770,root,cloud) %{_localstatedir}/%{name}/mnt
-%dir %attr(0770,cloud,cloud) %{_localstatedir}/%{name}/management
-%dir %attr(0770,root,cloud) %{_localstatedir}/cache/%{name}/management
-%dir %attr(0770,root,cloud) %{_localstatedir}/cache/%{name}/management/work
-%dir %attr(0770,root,cloud) %{_localstatedir}/cache/%{name}/management/temp
-%dir %attr(0770,root,cloud) %{_localstatedir}/log/%{name}/management
-%config(noreplace) %{_sysconfdir}/sysconfig/%{name}-management
-%config(noreplace) %attr(0640,root,cloud) %{_sysconfdir}/%{name}/management/db.properties
-%config(noreplace) %{_sysconfdir}/%{name}/management/log4j-cloud.xml
-%config(noreplace) %{_sysconfdir}/%{name}/management/tomcat6-nonssl.conf
-%config(noreplace) %{_sysconfdir}/%{name}/management/tomcat6-ssl.conf
-%config(noreplace) %{_sysconfdir}/%{name}/management/Catalina/localhost/client/context.xml
-%config(noreplace) %{_sysconfdir}/%{name}/management/catalina.policy
-%config(noreplace) %{_sysconfdir}/%{name}/management/catalina.properties
-%config(noreplace) %{_sysconfdir}/%{name}/management/classpath.conf
-%config(noreplace) %{_sysconfdir}/%{name}/management/server-nonssl.xml
-%config(noreplace) %{_sysconfdir}/%{name}/management/server-ssl.xml
-%config(noreplace) %{_sysconfdir}/%{name}/management/tomcat-users.xml
-%config(noreplace) %{_sysconfdir}/%{name}/management/web.xml
-%config(noreplace) %{_sysconfdir}/%{name}/management/environment.properties
-%config(noreplace) %{_sysconfdir}/%{name}/management/java.security.ciphers
-%config(noreplace) %{_sysconfdir}/%{name}/management/commons-logging.properties
-%attr(0755,root,root) %{_initrddir}/%{name}-management
-%attr(0755,root,root) %{_initrddir}/tomcat.sh
-
-%attr(0755,root,root) %{_bindir}/%{name}-setup-management
-%attr(0755,root,root) %{_bindir}/%{name}-update-xenserver-licenses
-%{_datadir}/%{name}-management/webapps
-%{_datadir}/%{name}-management/bin
-%{_datadir}/%{name}-management/conf
-%{_datadir}/%{name}-management/lib
-%{_datadir}/%{name}-management/logs
-%{_datadir}/%{name}-management/temp
-%{_datadir}/%{name}-management/work
-%attr(0755,root,root) %{_bindir}/%{name}-setup-databases
-%attr(0755,root,root) %{_bindir}/%{name}-migrate-databases
-%attr(0755,root,root) %{_bindir}/%{name}-set-guest-password
-%attr(0755,root,root) %{_bindir}/%{name}-set-guest-sshkey
-%attr(0755,root,root) %{_bindir}/%{name}-sysvmadm
-%attr(0755,root,root) %{_bindir}/%{name}-setup-encryption
-%{_datadir}/%{name}-management/setup/*.sql
-%{_datadir}/%{name}-management/setup/db/*.sql
-%{_datadir}/%{name}-management/setup/*.sh
-%{_datadir}/%{name}-management/setup/server-setup.xml
-%attr(0755,root,root) %{_bindir}/%{name}-external-ipallocator.py
-%attr(0755,root,root) %{_initrddir}/%{name}-ipallocator
-%dir %attr(0770,root,root) %{_localstatedir}/log/%{name}/ipallocator
-%{_defaultdocdir}/%{name}-management-%{version}/LICENSE
-%{_defaultdocdir}/%{name}-management-%{version}/NOTICE
-%attr(0644,cloud,cloud) %{_localstatedir}/log/%{name}/management/catalina.out
-%attr(0644,root,root) %{_sysconfdir}/logrotate.d/%{name}-catalina
-
-%files agent
-%attr(0755,root,root) %{_bindir}/%{name}-setup-agent
-%attr(0755,root,root) %{_bindir}/%{name}-agent-upgrade
-%attr(0755,root,root) %{_bindir}/%{name}-ssh
-%attr(0755,root,root) %{_sysconfdir}/init.d/%{name}-agent
-%attr(0644,root,root) %{_sysconfdir}/profile.d/%{name}-agent-profile.sh
-%attr(0644,root,root) %{_sysconfdir}/logrotate.d/%{name}-agent
-%attr(0755,root,root) %{_datadir}/%{name}-common/scripts/network/cisco
-%config(noreplace) %{_sysconfdir}/%{name}/agent
-%dir %{_localstatedir}/log/%{name}/agent
-%attr(0644,root,root) %{_datadir}/%{name}-agent/lib/*.jar
-%attr(0755,root,root) %{_datadir}/%{name}-agent/lib/libvirtqemuhook
-%dir %{_datadir}/%{name}-agent/plugins
-%{_defaultdocdir}/%{name}-agent-%{version}/LICENSE
-%{_defaultdocdir}/%{name}-agent-%{version}/NOTICE
-
-%files common
-%dir %attr(0755,root,root) %{python_sitearch}/cloudutils
-%dir %attr(0755,root,root) %{_datadir}/%{name}-common/vms
-%attr(0755,root,root) %{_datadir}/%{name}-common/scripts
-%attr(0755,root,root) /usr/bin/cloudstack-sccs
-%attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso
-%attr(0644,root,root) %{python_sitearch}/cloud_utils.py
-%attr(0644,root,root) %{python_sitearch}/cloud_utils.pyc
-%attr(0644,root,root) %{python_sitearch}/cloudutils/*
-%attr(0644, root, root) %{_datadir}/%{name}-common/lib/jasypt-1.9.2.jar
-%{_defaultdocdir}/%{name}-common-%{version}/LICENSE
-%{_defaultdocdir}/%{name}-common-%{version}/NOTICE
-
-%files usage
-%attr(0755,root,root) %{_sysconfdir}/init.d/%{name}-usage
-%attr(0644,root,root) %{_datadir}/%{name}-usage/*.jar
-%attr(0644,root,root) %{_datadir}/%{name}-usage/lib/*.jar
-%dir %attr(0770,root,cloud) %{_localstatedir}/log/%{name}/usage
-%attr(0644,root,root) %{_sysconfdir}/%{name}/usage/db.properties
-%attr(0644,root,root) %{_sysconfdir}/%{name}/usage/log4j-cloud.xml
-%{_defaultdocdir}/%{name}-usage-%{version}/LICENSE
-%{_defaultdocdir}/%{name}-usage-%{version}/NOTICE
-
-%files cli
-%attr(0644,root,root) %{python_sitearch}/cloudapis.py
-%attr(0644,root,root) %{python_sitearch}/cloudtool/__init__.py
-%attr(0644,root,root) %{python_sitearch}/cloudtool/utils.py
-%{_defaultdocdir}/%{name}-cli-%{version}/LICENSE
-%{_defaultdocdir}/%{name}-cli-%{version}/NOTICE
-
-%if "%{_ossnoss}" == "noredist"
-%files mysql-ha
-%defattr(0644,cloud,cloud,0755)
-%attr(0644,root,root) %{_datadir}/%{name}-mysql-ha/lib/*
-%{_defaultdocdir}/%{name}-mysql-ha-%{version}/LICENSE
-%{_defaultdocdir}/%{name}-mysql-ha-%{version}/NOTICE
-%endif
-
-%files baremetal-agent
-%attr(0755,root,root) %{_bindir}/cloudstack-setup-baremetal
-
-%changelog
-* Thu Apr 30 2015 Rohit Yadav <bh...@apache.org> 4.6.0
-- Remove awsapi package
-
-* Fri Jul 04 2014 Hugo Trippaers <hu...@apache.org> 4.5.0
-- Add a package for the mysql ha module
-
-* Wed Oct 03 2012 Hugo Trippaers <hu...@apache.org> 4.1.0
-- new style spec file
diff --git a/packaging/fedora20/cloudstack-agent.te b/packaging/fedora20/cloudstack-agent.te
deleted file mode 100644
index 4259e173a46..00000000000
--- a/packaging/fedora20/cloudstack-agent.te
+++ /dev/null
@@ -1,33 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-module cloudstack-agent 1.0;
-
-require {
- type nfs_t;
- type system_conf_t;
- type mount_t;
- type qemu_t;
- class file unlink;
- class filesystem getattr;
-}
-
-#============= mount_t ==============
-allow mount_t system_conf_t:file unlink;
-
-#============= qemu_t ==============
-allow qemu_t nfs_t:filesystem getattr;
diff --git a/packaging/fedora20/replace.properties b/packaging/fedora20/replace.properties
deleted file mode 100644
index bdf6e223b59..00000000000
--- a/packaging/fedora20/replace.properties
+++ /dev/null
@@ -1,59 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-DBUSER=cloud
-DBPW=cloud
-DBROOTPW=
-MSLOG=vmops.log
-APISERVERLOG=api.log
-DBHOST=localhost
-DBDRIVER=jdbc:mysql
-COMPONENTS-SPEC=components-premium.xml
-REMOTEHOST=localhost
-AGENTCLASSPATH=
-AGENTLOG=/var/log/cloudstack/agent/agent.log
-AGENTLOGDIR=/var/log/cloudstack/agent/
-AGENTSYSCONFDIR=/etc/cloudstack/agent
-APISERVERLOG=/var/log/cloudstack/management/apilog.log
-BINDIR=/usr/bin
-COMMONLIBDIR=/usr/share/cloudstack-common
-CONFIGUREVARS=
-DEPSCLASSPATH=
-DOCDIR=
-IPALOCATORLOG=/var/log/cloudstack/management/ipallocator.log
-JAVADIR=/usr/share/java
-LIBEXECDIR=/usr/libexec
-LOCKDIR=/var/lock
-MSCLASSPATH=
-MSCONF=/etc/cloudstack/management
-MSENVIRON=/usr/share/cloudstack-management
-MSLOG=/var/log/cloudstack/management/management-server.log
-MSLOGDIR=/var/log/cloudstack/management/
-MSMNTDIR=/var/cloudstack/mnt
-MSUSER=cloud
-PIDDIR=/var/run
-PLUGINJAVADIR=/usr/share/cloudstack-management/plugin
-PREMIUMJAVADIR=/usr/share/cloudstack-management/premium
-PYTHONDIR=/usr/lib/python2.6/site-packages/
-SERVERSYSCONFDIR=/etc/sysconfig
-SETUPDATADIR=/usr/share/cloudstack-management/setup
-SYSCONFDIR=/etc/sysconfig
-SYSTEMCLASSPATH=
-SYSTEMJARS=
-USAGECLASSPATH=
-USAGELOG=/var/log/cloudstack/usage/usage.log
-USAGESYSCONFDIR=/etc/sysconfig
diff --git a/packaging/fedora21/cloud-agent.rc b/packaging/fedora21/cloud-agent.rc
deleted file mode 100755
index 2defa148883..00000000000
--- a/packaging/fedora21/cloud-agent.rc
+++ /dev/null
@@ -1,118 +0,0 @@
-#!/bin/bash
-
-# chkconfig: 35 99 10
-# description: Cloud Agent
-# pidfile: /var/run/cloudstack-agent.pid
-
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# WARNING: if this script is changed, then all other initscripts MUST BE changed to match it as well
-
-. /etc/rc.d/init.d/functions
-
-# set environment variables
-
-SHORTNAME=$(basename $0 | sed -e 's/^[SK][0-9][0-9]//')
-PIDFILE=/var/run/"$SHORTNAME".pid
-LOCKFILE=/var/lock/subsys/"$SHORTNAME"
-LOGDIR=/var/log/cloudstack/agent
-LOGFILE=${LOGDIR}/agent.log
-PROGNAME="Cloud Agent"
-CLASS="com.cloud.agent.AgentShell"
-JSVC=`which jsvc 2>/dev/null`;
-
-# exit if we don't find jsvc
-if [ -z "$JSVC" ]; then
- echo no jsvc found in path;
- exit 1;
-fi
-
-unset OPTIONS
-[ -r /etc/sysconfig/"$SHORTNAME" ] && source /etc/sysconfig/"$SHORTNAME"
-
-# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT)
-JDK_DIRS="/usr/lib/jvm/jre /usr/lib/jvm/java-7-openjdk /usr/lib/jvm/java-7-openjdk-i386 /usr/lib/jvm/java-7-openjdk-amd64 /usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-openjdk-i386 /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-6-sun"
-
-for jdir in $JDK_DIRS; do
- if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then
- JAVA_HOME="$jdir"
- fi
-done
-export JAVA_HOME
-
-ACP=`ls /usr/share/cloudstack-agent/lib/*.jar | tr '\n' ':' | sed s'/.$//'`
-PCP=`ls /usr/share/cloudstack-agent/plugins/*.jar 2>/dev/null | tr '\n' ':' | sed s'/.$//'`
-
-# We need to append the JSVC daemon JAR to the classpath
-# AgentShell implements the JSVC daemon methods
-export CLASSPATH="/usr/share/java/commons-daemon.jar:$ACP:$PCP:/etc/cloudstack/agent:/usr/share/cloudstack-common/scripts"
-
-start() {
- echo -n $"Starting $PROGNAME: "
- if hostname --fqdn >/dev/null 2>&1 ; then
- $JSVC -Xms256m -Xmx2048m -cp "$CLASSPATH" -pidfile "$PIDFILE" \
- -errfile $LOGDIR/cloudstack-agent.err -outfile $LOGDIR/cloudstack-agent.out $CLASS
- RETVAL=$?
- echo
- else
- failure
- echo
- echo The host name does not resolve properly to an IP address. Cannot start "$PROGNAME". > /dev/stderr
- RETVAL=9
- fi
- [ $RETVAL = 0 ] && touch ${LOCKFILE}
- return $RETVAL
-}
-
-stop() {
- echo -n $"Stopping $PROGNAME: "
- $JSVC -pidfile "$PIDFILE" -stop $CLASS
- RETVAL=$?
- echo
- [ $RETVAL = 0 ] && rm -f ${LOCKFILE} ${PIDFILE}
-}
-
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- status)
- status -p ${PIDFILE} $SHORTNAME
- RETVAL=$?
- ;;
- restart)
- stop
- sleep 3
- start
- ;;
- condrestart)
- if status -p ${PIDFILE} $SHORTNAME >&/dev/null; then
- stop
- sleep 3
- start
- fi
- ;;
- *)
- echo $"Usage: $SHORTNAME {start|stop|restart|condrestart|status|help}"
- RETVAL=3
-esac
-
-exit $RETVAL
diff --git a/packaging/fedora21/cloud-ipallocator.rc b/packaging/fedora21/cloud-ipallocator.rc
deleted file mode 100755
index d3eadec8a82..00000000000
--- a/packaging/fedora21/cloud-ipallocator.rc
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/bin/bash
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# chkconfig: 35 99 10
-# description: Cloud Agent
-
-# WARNING: if this script is changed, then all other initscripts MUST BE changed to match it as well
-
-. /etc/rc.d/init.d/functions
-
-# set environment variables
-
-SHORTNAME="$(basename $(readlink -f $0))"
-PIDFILE=/var/run/"$SHORTNAME".pid
-LOCKFILE=/var/lock/subsys/"$SHORTNAME"
-LOGFILE=/var/log/cloudstack/ipallocator/ipallocator.log
-PROGNAME="External IPAllocator"
-
-unset OPTIONS
-[ -r /etc/sysconfig/"$SHORTNAME" ] && source /etc/sysconfig/"$SHORTNAME"
-DAEMONIZE=/usr/bin/cloud-daemonize
-PROG=/usr/bin/cloud-external-ipallocator.py
-OPTIONS=8083
-
-start() {
- echo -n $"Starting $PROGNAME: "
- if hostname --fqdn >/dev/null 2>&1 ; then
- daemon --check=$SHORTNAME --pidfile=${PIDFILE} "$DAEMONIZE" \
- -n "$SHORTNAME" -p "$PIDFILE" -l "$LOGFILE" "$PROG" $OPTIONS
- RETVAL=$?
- echo
- else
- failure
- echo
- echo The host name does not resolve properly to an IP address. Cannot start "$PROGNAME". > /dev/stderr
- RETVAL=9
- fi
- [ $RETVAL = 0 ] && touch ${LOCKFILE}
- return $RETVAL
-}
-
-stop() {
- echo -n $"Stopping $PROGNAME: "
- killproc -p ${PIDFILE} $SHORTNAME # -d 10 $SHORTNAME
- RETVAL=$?
- echo
- [ $RETVAL = 0 ] && rm -f ${LOCKFILE} ${PIDFILE}
-}
-
-
-# See how we were called.
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- status)
- status -p ${PIDFILE} $SHORTNAME
- RETVAL=$?
- ;;
- restart)
- stop
- sleep 3
- start
- ;;
- condrestart)
- if status -p ${PIDFILE} $SHORTNAME >&/dev/null; then
- stop
- sleep 3
- start
- fi
- ;;
- *)
- echo $"Usage: $SHORTNAME {start|stop|restart|condrestart|status|help}"
- RETVAL=3
-esac
-
-exit $RETVAL
-
diff --git a/packaging/fedora21/cloud-management.rc b/packaging/fedora21/cloud-management.rc
deleted file mode 100755
index f5ed7a8048a..00000000000
--- a/packaging/fedora21/cloud-management.rc
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/bin/bash
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-# cloudstack-management This shell script takes care of starting and stopping Tomcat
-#
-# chkconfig: - 80 20
-#
-### BEGIN INIT INFO
-# Provides: tomcat6
-# Required-Start: $network $syslog
-# Required-Stop: $network $syslog
-# Default-Start:
-# Default-Stop:
-# Description: Release implementation for Servlet 2.5 and JSP 2.1
-# Short-Description: start and stop tomcat
-### END INIT INFO
-#
-# - originally written by Henri Gomez, Keith Irwin, and Nicolas Mailhot
-# - heavily rewritten by Deepak Bhole and Jason Corley
-#
-
-if [ -r /etc/rc.d/init.d/functions ]; then
- . /etc/rc.d/init.d/functions
-fi
-if [ -r /lib/lsb/init-functions ]; then
- . /lib/lsb/init-functions
-fi
-
-
-NAME="$(basename $(readlink -f $0))"
-export SERVICE_NAME="$NAME"
-stop() {
- SHUTDOWN_WAIT="30"
- count="0"
- if [ -f /var/run/${NAME}.pid ]; then
- pid=`cat /var/run/${NAME}.pid`
- kill $pid &>/dev/null
- until [ "$(ps --pid $pid | grep -c $pid)" -eq "0" ] || \
- [ "$count" -gt "$SHUTDOWN_WAIT" ]
- do
- sleep 1
- let count="${count}+1"
- done
- if [ "$(ps --pid $pid | grep -c $pid)" -eq "0" ]; then
- log_success_msg "Stopping ${NAME}:"
- rm -f /var/run/${NAME}.pid
- rm -f /var/lock/subsys/${NAME}
- else
- log_failure_msg "Stopping ${NAME}:"
- fi
- else
- echo "Cannot find PID file of ${NAME}"
- log_failure_msg "Stopping ${NAME}:"
- fi
-}
-
-set_ulimit() {
- fd_limit=`ulimit -n`
- if [ "$fd_limit" != "4096" ]; then
- user=`whoami`
- if [ $user == "root" ]; then
- ulimit -n 4096
- fi
- fi
-}
-
-handle_pid_file() {
- if [ "$1" -ne 0 ] && [ "$1" -ne 3 ]; then
- echo "The pid file locates at /var/run/${NAME}.pid and lock file at /var/lock/subsys/${NAME}.
- Starting ${NAME} will take care of them or you can manually clean up."
- fi
-}
-
-start() {
- readpath=$(readlink -f $0)
- source `dirname $readpath`/tomcat.sh
-}
-
-# See how we were called.
-case "$1" in
- status)
- status ${NAME}
- RETVAL=$?
- handle_pid_file $RETVAL
- ;;
- stop)
- stop
- ;;
- restart)
- stop
- set start
- set_ulimit
- start
- ;;
- *)
- set_ulimit
- start
-esac
-
-exit $RETVAL
diff --git a/packaging/fedora21/cloud-management.sysconfig b/packaging/fedora21/cloud-management.sysconfig
deleted file mode 100644
index cbc8b8b36c1..00000000000
--- a/packaging/fedora21/cloud-management.sysconfig
+++ /dev/null
@@ -1,23 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# This file is loaded in /etc/init.d/vmopsmanagement
-# ATM we only do two things here:
-
-dummy=1 ; export TOMCAT_CFG=/etc/cloudstack/management/tomcat6.conf ; . /etc/cloudstack/management/tomcat6.conf
-#--------------------------
-
diff --git a/packaging/fedora21/cloud-usage.rc b/packaging/fedora21/cloud-usage.rc
deleted file mode 100755
index 774113745d7..00000000000
--- a/packaging/fedora21/cloud-usage.rc
+++ /dev/null
@@ -1,156 +0,0 @@
-#!/bin/bash
-
-### BEGIN INIT INFO
-# Provides: cloudstack-usage
-# Required-Start: $network $local_fs
-# Required-Stop: $network $local_fs
-# Default-Start: 3 4 5
-# Default-Stop: 0 1 2 6
-# Short-Description: Start/stop Apache CloudStack Usage Monitor
-# Description: This scripts Starts/Stops the Apache CloudStack Usage Monitor
-## The CloudStack Usage Monitor is a part of the Apache CloudStack project and is used
-## for storing usage statistics from instances.
-## JSVC (Java daemonizing) is used for starting and stopping the usage monitor.
-### END INIT INFO
-
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-. /etc/rc.d/init.d/functions
-
-SHORTNAME="cloudstack-usage"
-PIDFILE=/var/run/"$SHORTNAME".pid
-LOCKFILE=/var/lock/subsys/"$SHORTNAME"
-LOGDIR=/var/log/cloudstack/usage
-LOGFILE=${LOGDIR}/usage.log
-PROGNAME="CloudStack Usage Monitor"
-CLASS="com.cloud.usage.UsageServer"
-PROG="jsvc"
-DAEMON="/usr/bin/jsvc"
-USER=cloud
-
-unset OPTIONS
-[ -r /etc/sysconfig/default/"$SHORTNAME" ] && source /etc/sysconfig/default/"$SHORTNAME"
-
-setJavaHome() {
- # use $JAVA_HOME if defined
- if [ -n "$JAVA_HOME" ] ; then
- return
- fi
-
- # try java first
- java=$(which java 2>/dev/null || :)
-
- # try javac if java is not found
- if [ -z "$java" ] ; then
- java=$(which javac 2>/dev/null || :)
- fi
-
- if [ -n "$java" ] ; then
- JAVA_HOME=$(dirname $(dirname $(readlink -e $java)))
- export JAVA_HOME
- return
- fi
-
- # didnt find java home. exiting with error
- exit 1
-}
-
-setJavaHome
-
-SCP=""
-DCP=""
-UCP=`ls /usr/share/cloudstack-usage/cloud-usage-*.jar`":"`ls /usr/share/cloudstack-usage/lib/*.jar | tr '\n' ':'`
-JCP="/usr/share/java/commons-daemon.jar":"/usr/share/java/mysql-connector-java.jar"
-
-# We need to append the JSVC daemon and mysql-connector JAR to the classpath
-# AgentShell implements the JSVC daemon methods
-export CLASSPATH="$SCP:$DCP:$UCP:$JCP:/etc/cloudstack/usage"
-
-start() {
- if [ -s "$PIDFILE" ] && kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then
- echo "$PROGNAME apparently already running"
- exit 0
- fi
-
- if hostname --fqdn >/dev/null 2>&1 ; then
- true
- else
- echo "The host name does not resolve properly to an IP address. Cannot start $PROGNAME"
- exit 1
- fi
-
- echo -n "Starting $PROGNAME" "$SHORTNAME"
-
- if daemon --pidfile $PIDFILE $DAEMON -home "$JAVA_HOME" -cp "$CLASSPATH" -pidfile "$PIDFILE" -user "$USER" \
- -errfile $LOGDIR/cloudstack-usage.err -outfile $LOGDIR/cloudstack-usage.out -Dpid=$$ $CLASS
- RETVAL=$?
- then
- rc=0
- sleep 1
- if ! kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then
- failure
- rc=1
- fi
- else
- rc=1
- fi
-
- if [ $rc -eq 0 ]; then
- success
- else
- failure
- rm -f "$PIDFILE"
- fi
- echo
-}
-
-stop() {
- echo -n "Stopping $PROGNAME" "$SHORTNAME"
- killproc -p $PIDFILE $DAEMON
- if [ "$?" -eq 0 ]; then
- success
- else
- failure
- fi
- rm -f "$PIDFILE"
- echo
-}
-
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- status)
- status -p $PIDFILE $SHORTNAME
- RETVAL=$?
- ;;
- restart | force-reload)
- stop
- sleep 3
- start
- ;;
- *)
- echo "Usage: $0 {start|stop|restart|force-reload|status}"
- RETVAL=3
-esac
-
-exit $RETVAL
-
diff --git a/packaging/fedora21/cloud.spec b/packaging/fedora21/cloud.spec
deleted file mode 100644
index a79d172eab7..00000000000
--- a/packaging/fedora21/cloud.spec
+++ /dev/null
@@ -1,655 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-%define __os_install_post %{nil}
-%global debug_package %{nil}
-
-# DISABLE the post-percentinstall java repacking and line number stripping
-# we need to find a way to just disable the java repacking and line number stripping, but not the autodeps
-
-Name: cloudstack
-Summary: CloudStack IaaS Platform
-#http://fedoraproject.org/wiki/PackageNamingGuidelines#Pre-Release_packages
-%if "%{?_prerelease}" != ""
-%define _maventag %{_ver}-SNAPSHOT
-Release: %{_rel}%{dist}
-%else
-%define _maventag %{_ver}
-Release: %{_rel}%{dist}
-%endif
-
-%{!?python_sitearch: %define python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(1))")}
-
-Version: %{_ver}
-License: ASL 2.0
-Vendor: Apache CloudStack <de...@cloudstack.apache.org>
-Packager: Apache CloudStack <de...@cloudstack.apache.org>
-Group: System Environment/Libraries
-# FIXME do groups for every single one of the subpackages
-Source0: %{name}-%{_maventag}.tgz
-BuildRoot: %{_tmppath}/%{name}-%{_maventag}-%{release}-build
-
-BuildRequires: java-1.8.0-openjdk-devel
-BuildRequires: tomcat
-BuildRequires: ws-commons-util
-BuildRequires: jpackage-utils
-BuildRequires: gcc
-BuildRequires: glibc-devel
-BuildRequires: /usr/bin/mkisofs
-BuildRequires: mysql-connector-python
-#BuildRequires: maven => 3.0.0
-
-%description
-CloudStack is a highly-scalable elastic, open source,
-intelligent IaaS cloud implementation.
-
-%package management
-Summary: CloudStack management server UI
-Requires: tomcat
-Requires: java-1.8.0-openjdk
-Requires: python
-Requires: bash
-Requires: bzip2
-Requires: gzip
-Requires: unzip
-Requires: /sbin/mount.nfs
-Requires: openssh-clients
-Requires: nfs-utils
-Requires: wget
-Requires: mysql
-Requires: mysql-connector-java
-Requires: ws-commons-util
-Requires: jpackage-utils
-Requires: sudo
-Requires: /sbin/service
-Requires: /sbin/chkconfig
-Requires: /usr/bin/ssh-keygen
-Requires: mkisofs
-Requires: mysql-connector-python
-Requires: python-paramiko
-Requires: ipmitool
-Requires: %{name}-common = %{_ver}
-Obsoletes: cloud-client < 4.1.0
-Obsoletes: cloud-client-ui < 4.1.0
-Obsoletes: cloud-server < 4.1.0
-Obsoletes: cloud-test < 4.1.0
-Provides: cloud-client
-Group: System Environment/Libraries
-%description management
-The CloudStack management server is the central point of coordination,
-management, and intelligence in CloudStack.
-
-%package common
-Summary: Apache CloudStack common files and scripts
-Requires: python
-Obsoletes: cloud-test < 4.1.0
-Obsoletes: cloud-scripts < 4.1.0
-Obsoletes: cloud-utils < 4.1.0
-Obsoletes: cloud-core < 4.1.0
-Obsoletes: cloud-deps < 4.1.0
-Obsoletes: cloud-python < 4.1.0
-Obsoletes: cloud-setup < 4.1.0
-Obsoletes: cloud-cli < 4.1.0
-Obsoletes: cloud-daemonize < 4.1.0
-Group: System Environment/Libraries
-%description common
-The Apache CloudStack files shared between agent and management server
-
-%package agent
-Summary: CloudStack Agent for KVM hypervisors
-Requires: openssh-clients
-Requires: java-1.8.0-openjdk
-Requires: %{name}-common = %{_ver}
-Requires: libvirt
-Requires: bridge-utils
-Requires: ebtables
-Requires: iptables
-Requires: ethtool
-Requires: vconfig
-Requires: ipset
-Requires: jsvc
-Requires: jakarta-commons-daemon
-Requires: jakarta-commons-daemon-jsvc
-Requires: perl
-Requires: libvirt-python
-Requires: qemu-img
-Requires: qemu-kvm
-Requires: libcgroup-tools
-Requires: net-tools
-Provides: cloud-agent
-Obsoletes: cloud-agent < 4.1.0
-Obsoletes: cloud-agent-libs < 4.1.0
-Obsoletes: cloud-test < 4.1.0
-Group: System Environment/Libraries
-%description agent
-The CloudStack agent for KVM hypervisors
-
-%package baremetal-agent
-Summary: CloudStack baremetal agent
-Requires: tftp-server
-Requires: xinetd
-Requires: syslinux
-Requires: chkconfig
-Requires: dhcp
-Requires: httpd
-Group: System Environment/Libraries
-%description baremetal-agent
-The CloudStack baremetal agent
-
-%package usage
-Summary: CloudStack Usage calculation server
-Requires: java-1.8.0-openjdk
-Requires: jsvc
-Requires: jakarta-commons-daemon
-Requires: jakarta-commons-daemon-jsvc
-Group: System Environment/Libraries
-Obsoletes: cloud-usage < 4.1.0
-Provides: cloud-usage
-%description usage
-The CloudStack usage calculation service
-
-%package cli
-Summary: Apache CloudStack CLI
-Provides: python-cloudmonkey
-Provides: python-marvin
-Group: System Environment/Libraries
-%description cli
-Apache CloudStack command line interface
-
-%if "%{_ossnoss}" == "noredist"
-%package mysql-ha
-Summary: Apache CloudStack Balancing Strategy for MySQL
-Requires: mysql-connector-java
-Requires: tomcat
-Group: System Environmnet/Libraries
-%description mysql-ha
-Apache CloudStack Balancing Strategy for MySQL
-
-%endif
-
-%prep
-echo Doing CloudStack build
-
-%setup -q -n %{name}-%{_maventag}
-
-%build
-
-cp packaging/centos63/replace.properties build/replace.properties
-echo VERSION=%{_maventag} >> build/replace.properties
-echo PACKAGE=%{name} >> build/replace.properties
-touch build/gitrev.txt
-echo $(git rev-parse HEAD) > build/gitrev.txt
-
-if [ "%{_ossnoss}" == "NOREDIST" -o "%{_ossnoss}" == "noredist" ] ; then
- echo "Executing mvn packaging with non-redistributable libraries"
- if [ "%{_sim}" == "SIMULATOR" -o "%{_sim}" == "simulator" ] ; then
- echo "Executing mvn noredist packaging with simulator ..."
- mvn -Psystemvm -Dnoredist -Dsimulator clean package
- else
- echo "Executing mvn noredist packaging without simulator..."
- mvn -Psystemvm -Dnoredist clean package
- fi
-else
- if [ "%{_sim}" == "SIMULATOR" -o "%{_sim}" == "simulator" ] ; then
- echo "Executing mvn default packaging simulator ..."
- mvn -Psystemvm -Dsimulator clean package
- else
- echo "Executing mvn default packaging without simulator ..."
- mvn -Psystemvm clean package
- fi
-fi
-
-%install
-[ ${RPM_BUILD_ROOT} != "/" ] && rm -rf ${RPM_BUILD_ROOT}
-# Common directories
-mkdir -p ${RPM_BUILD_ROOT}%{_bindir}
-mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/agent
-mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/ipallocator
-mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/cache/%{name}/management/work
-mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/cache/%{name}/management/temp
-mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/%{name}/mnt
-mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/%{name}/management
-mkdir -p ${RPM_BUILD_ROOT}%{_initrddir}
-mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig
-mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/profile.d
-
-# Common
-mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts
-mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms
-mkdir -p ${RPM_BUILD_ROOT}%{python_sitearch}/
-mkdir -p ${RPM_BUILD_ROOT}%/usr/bin
-cp -r scripts/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts
-install -D systemvm/dist/systemvm.iso ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/systemvm.iso
-install python/lib/cloud_utils.py ${RPM_BUILD_ROOT}%{python_sitearch}/cloud_utils.py
-cp -r python/lib/cloudutils ${RPM_BUILD_ROOT}%{python_sitearch}/
-python -m py_compile ${RPM_BUILD_ROOT}%{python_sitearch}/cloud_utils.py
-python -m compileall ${RPM_BUILD_ROOT}%{python_sitearch}/cloudutils
-cp build/gitrev.txt ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts
-cp packaging/centos63/cloudstack-sccs ${RPM_BUILD_ROOT}/usr/bin
-
-mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts/network/cisco
-cp -r plugins/network-elements/cisco-vnmc/scripts/network/cisco/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts/network/cisco
-
-# Management
-mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/
-mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client
-mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/setup
-mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/management
-mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management
-
-# Specific for tomcat
-mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/Catalina/localhost/client
-ln -sf /usr/share/tomcat/bin ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/bin
-ln -sf /etc/%{name}/management ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/conf
-ln -sf /usr/share/tomcat/lib ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/lib
-ln -sf /var/log/%{name}/management ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/logs
-ln -sf /var/cache/%{name}/management/temp ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/temp
-ln -sf /var/cache/%{name}/management/work ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/work
-
-/bin/touch ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/management/catalina.out
-
-install -D client/target/utilities/bin/cloud-migrate-databases ${RPM_BUILD_ROOT}%{_bindir}/%{name}-migrate-databases
-install -D client/target/utilities/bin/cloud-set-guest-password ${RPM_BUILD_ROOT}%{_bindir}/%{name}-set-guest-password
-install -D client/target/utilities/bin/cloud-set-guest-sshkey ${RPM_BUILD_ROOT}%{_bindir}/%{name}-set-guest-sshkey
-install -D client/target/utilities/bin/cloud-setup-databases ${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-databases
-install -D client/target/utilities/bin/cloud-setup-encryption ${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-encryption
-install -D client/target/utilities/bin/cloud-setup-management ${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-management
-install -D client/target/utilities/bin/cloud-setup-baremetal ${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-baremetal
-install -D client/target/utilities/bin/cloud-sysvmadm ${RPM_BUILD_ROOT}%{_bindir}/%{name}-sysvmadm
-install -D client/target/utilities/bin/cloud-update-xenserver-licenses ${RPM_BUILD_ROOT}%{_bindir}/%{name}-update-xenserver-licenses
-
-cp -r client/target/utilities/scripts/db/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/setup
-cp -r client/target/cloud-client-ui-%{_maventag}/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client
-
-# Don't package the scripts in the management webapp
-rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/scripts
-rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/vms
-
-for name in db.properties log4j-cloud.xml tomcat6-nonssl.conf tomcat6-ssl.conf server-ssl.xml server-nonssl.xml \
- catalina.policy catalina.properties classpath.conf tomcat-users.xml web.xml environment.properties java.security.ciphers ; do
- mv ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/$name \
- ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/$name
-done
-
-ln -s %{_sysconfdir}/%{name}/management/log4j-cloud.xml \
- ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/log4j-cloud.xml
-
-mv ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/context.xml \
- ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/Catalina/localhost/client
-
-install python/bindir/cloud-external-ipallocator.py ${RPM_BUILD_ROOT}%{_bindir}/%{name}-external-ipallocator.py
-install -D client/target/pythonlibs/jasypt-1.9.2.jar ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/lib/jasypt-1.9.2.jar
-
-install -D packaging/centos63/cloud-ipallocator.rc ${RPM_BUILD_ROOT}%{_initrddir}/%{name}-ipallocator
-install -D packaging/centos63/cloud-management.rc ${RPM_BUILD_ROOT}%{_initrddir}/%{name}-management
-install -D packaging/centos63/cloud-management.sysconfig ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig/%{name}-management
-install -D packaging/centos63/tomcat.sh ${RPM_BUILD_ROOT}%{_initrddir}/tomcat.sh
-install -D server/target/conf/cloudstack-catalina.logrotate ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/%{name}-catalina
-
-chmod 440 ${RPM_BUILD_ROOT}%{_sysconfdir}/sudoers.d/%{name}-management
-chmod 770 ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/Catalina
-chmod 770 ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/Catalina/localhost
-chmod 770 ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/Catalina/localhost/client
-chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/%{name}/mnt
-chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/%{name}/management
-chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/cache/%{name}/management/work
-chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/cache/%{name}/management/temp
-chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/management
-chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/agent
-
-# KVM Agent
-mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/agent
-mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/agent
-mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-agent/lib
-mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-agent/plugins
-install -D packaging/centos63/cloud-agent.rc ${RPM_BUILD_ROOT}%{_sysconfdir}/init.d/%{name}-agent
-install -D agent/target/transformed/agent.properties ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/agent/agent.properties
-install -D agent/target/transformed/environment.properties ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/agent/environment.properties
-install -D agent/target/transformed/log4j-cloud.xml ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/agent/log4j-cloud.xml
-install -D agent/target/transformed/cloud-setup-agent ${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-agent
-install -D agent/target/transformed/cloudstack-agent-upgrade ${RPM_BUILD_ROOT}%{_bindir}/%{name}-agent-upgrade
-install -D agent/target/transformed/libvirtqemuhook ${RPM_BUILD_ROOT}%{_datadir}/%{name}-agent/lib/libvirtqemuhook
-install -D agent/target/transformed/cloud-ssh ${RPM_BUILD_ROOT}%{_bindir}/%{name}-ssh
-install -D agent/target/transformed/cloudstack-agent-profile.sh ${RPM_BUILD_ROOT}%{_sysconfdir}/profile.d/%{name}-agent-profile.sh
-install -D agent/target/transformed/cloudstack-agent.logrotate ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/%{name}-agent
-install -D plugins/hypervisors/kvm/target/cloud-plugin-hypervisor-kvm-%{_maventag}.jar ${RPM_BUILD_ROOT}%{_datadir}/%name-agent/lib/cloud-plugin-hypervisor-kvm-%{_maventag}.jar
-cp plugins/hypervisors/kvm/target/dependencies/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-agent/lib
-
-# Usage server
-mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/usage
-mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-usage/lib
-install -D usage/target/cloud-usage-%{_maventag}.jar ${RPM_BUILD_ROOT}%{_datadir}/%{name}-usage/cloud-usage-%{_maventag}.jar
-install -D usage/target/transformed/db.properties ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/usage/db.properties
-install -D usage/target/transformed/log4j-cloud_usage.xml ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/usage/log4j-cloud.xml
-cp usage/target/dependencies/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-usage/lib/
-install -D packaging/centos63/cloud-usage.rc ${RPM_BUILD_ROOT}/%{_sysconfdir}/init.d/%{name}-usage
-mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/usage/
-
-# CLI
-cp -r cloud-cli/cloudtool ${RPM_BUILD_ROOT}%{python_sitearch}/
-install cloud-cli/cloudapis/cloud.py ${RPM_BUILD_ROOT}%{python_sitearch}/cloudapis.py
-
-# MYSQL HA
-if [ "x%{_ossnoss}" == "xnoredist" ] ; then
- mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-mysql-ha/lib
- cp -r plugins/database/mysql-ha/target/cloud-plugin-database-mysqlha-%{_maventag}.jar ${RPM_BUILD_ROOT}%{_datadir}/%{name}-mysql-ha/lib
-fi
-
-#License files from whisker
-install -D tools/whisker/NOTICE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-management-%{version}/NOTICE
-install -D tools/whisker/LICENSE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-management-%{version}/LICENSE
-install -D tools/whisker/NOTICE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-common-%{version}/NOTICE
-install -D tools/whisker/LICENSE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-common-%{version}/LICENSE
-install -D tools/whisker/NOTICE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-agent-%{version}/NOTICE
-install -D tools/whisker/LICENSE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-agent-%{version}/LICENSE
-install -D tools/whisker/NOTICE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-usage-%{version}/NOTICE
-install -D tools/whisker/LICENSE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-usage-%{version}/LICENSE
-install -D tools/whisker/NOTICE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-cli-%{version}/NOTICE
-install -D tools/whisker/LICENSE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-cli-%{version}/LICENSE
-if [ "x%{_ossnoss}" == "xnoredist" ] ; then
- install -D tools/whisker/LICENSE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-mysql-ha-%{version}/LICENSE
- install -D tools/whisker/NOTICE ${RPM_BUILD_ROOT}%{_defaultdocdir}/%{name}-mysql-ha-%{version}/NOTICE
-fi
-
-%clean
-[ ${RPM_BUILD_ROOT} != "/" ] && rm -rf ${RPM_BUILD_ROOT}
-
-%preun management
-/sbin/service cloudstack-management stop || true
-if [ "$1" == "0" ] ; then
- /sbin/chkconfig --del cloudstack-management > /dev/null 2>&1 || true
- /sbin/service cloudstack-management stop > /dev/null 2>&1 || true
-fi
-
-%pre management
-id cloud > /dev/null 2>&1 || /usr/sbin/useradd -M -c "CloudStack unprivileged user" \
- -r -s /bin/sh -d %{_localstatedir}/cloudstack/management cloud|| true
-
-# set max file descriptors for cloud user to 4096
-sed -i /"cloud hard nofile"/d /etc/security/limits.conf
-sed -i /"cloud soft nofile"/d /etc/security/limits.conf
-echo "cloud hard nofile 4096" >> /etc/security/limits.conf
-echo "cloud soft nofile 4096" >> /etc/security/limits.conf
-rm -rf %{_localstatedir}/cache/cloud
-rm -rf %{_localstatedir}/cache/cloudstack
-# user harcoded here, also hardcoded on wscript
-
-# save old configs if they exist (for upgrade). Otherwise we may lose them
-# when the old packages are erased. There are a lot of properties files here.
-if [ -d "%{_sysconfdir}/cloud" ] ; then
- mv %{_sysconfdir}/cloud %{_sysconfdir}/cloud.rpmsave
-fi
-
-# in case of upgrade to 4.9+ copy commands.properties if not exists in /etc/cloudstack/management/
-if [ "$1" == "2" ] ; then
- if [ -f "%{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/commands.properties" ] && [ ! -f "%{_sysconfdir}/%{name}/management/commands.properties" ] ; then
- cp -p %{_datadir}/%{name}-management/webapps/client/WEB-INF/classes/commands.properties %{_sysconfdir}/%{name}/management/commands.properties
- fi
-fi
-
-%post management
-if [ "$1" == "1" ] ; then
- /sbin/chkconfig --add cloudstack-management > /dev/null 2>&1 || true
- /sbin/chkconfig --level 345 cloudstack-management on > /dev/null 2>&1 || true
-fi
-
-if [ ! -f %{_datadir}/cloudstack-common/scripts/vm/hypervisor/xenserver/vhd-util ] ; then
- echo Please download vhd-util from http://download.cloudstack.org/tools/vhd-util and put it in
- echo %{_datadir}/cloudstack-common/scripts/vm/hypervisor/xenserver/
-fi
-
-# change cloud user's home to 4.1+ version if needed. Would do this via 'usermod', but it
-# requires that cloud user not be in use, so RPM could not be installed while management is running
-if getent passwd cloud | grep -q /var/lib/cloud; then
- sed -i 's/\/var\/lib\/cloud\/management/\/var\/cloudstack\/management/g' /etc/passwd
-fi
-
-# if saved configs from upgrade exist, copy them over
-if [ -f "%{_sysconfdir}/cloud.rpmsave/management/db.properties" ]; then
- mv %{_sysconfdir}/%{name}/management/db.properties %{_sysconfdir}/%{name}/management/db.properties.rpmnew
- cp -p %{_sysconfdir}/cloud.rpmsave/management/db.properties %{_sysconfdir}/%{name}/management
- if [ -f "%{_sysconfdir}/cloud.rpmsave/management/key" ]; then
- cp -p %{_sysconfdir}/cloud.rpmsave/management/key %{_sysconfdir}/%{name}/management
- fi
- # make sure we only do this on the first install of this RPM, don't want to overwrite on a reinstall
- mv %{_sysconfdir}/cloud.rpmsave/management/db.properties %{_sysconfdir}/cloud.rpmsave/management/db.properties.rpmsave
-fi
-
-# Choose server.xml and tomcat.conf links based on old config, if exists
-serverxml=%{_sysconfdir}/%{name}/management/server.xml
-oldserverxml=%{_sysconfdir}/cloud.rpmsave/management/server.xml
-if [ -f $oldserverxml ] || [ -L $oldserverxml ]; then
- if stat -c %N $oldserverxml| grep -q server-ssl ; then
- if [ -f $serverxml ] || [ -L $serverxml ]; then rm -f $serverxml; fi
- ln -s %{_sysconfdir}/%{name}/management/server-ssl.xml $serverxml
- echo Please verify the server.xml in saved folder, and make the required changes manually , saved folder available at $oldserverxml
- else
- if [ -f $serverxml ] || [ -L $serverxml ]; then rm -f $serverxml; fi
- ln -s %{_sysconfdir}/%{name}/management/server-nonssl.xml $serverxml
- echo Please verify the server.xml in saved folder, and make the required changes manually , saved folder available at $oldserverxml
-
- fi
-else
- echo "Unable to determine ssl settings for server.xml, please run cloudstack-setup-management manually"
-fi
-
-
-tomcatconf=%{_sysconfdir}/%{name}/management/tomcat6.conf
-oldtomcatconf=%{_sysconfdir}/cloud.rpmsave/management/tomcat6.conf
-if [ -f $oldtomcatconf ] || [ -L $oldtomcatconf ] ; then
- if stat -c %N $oldtomcatconf| grep -q tomcat6-ssl ; then
- if [ -f $tomcatconf ] || [ -L $tomcatconf ]; then rm -f $tomcatconf; fi
- ln -s %{_sysconfdir}/%{name}/management/tomcat6-ssl.conf $tomcatconf
- echo Please verify the tomcat6.conf in saved folder, and make the required changes manually , saved folder available at $oldtomcatconf
- else
- if [ -f $tomcatconf ] || [ -L $tomcatconf ]; then rm -f $tomcatconf; fi
- ln -s %{_sysconfdir}/%{name}/management/tomcat6-nonssl.conf $tomcatconf
- echo Please verify the tomcat6.conf in saved folder, and make the required changes manually , saved folder available at $oldtomcatconf
- fi
-else
- echo "Unable to determine ssl settings for tomcat.conf, please run cloudstack-setup-management manually"
-fi
-
-if [ -f "%{_sysconfdir}/cloud.rpmsave/management/cloud.keystore" ]; then
- cp -p %{_sysconfdir}/cloud.rpmsave/management/cloud.keystore %{_sysconfdir}/%{name}/management/cloudmanagementserver.keystore
- # make sure we only do this on the first install of this RPM, don't want to overwrite on a reinstall
- mv %{_sysconfdir}/cloud.rpmsave/management/cloud.keystore %{_sysconfdir}/cloud.rpmsave/management/cloud.keystore.rpmsave
-fi
-
-%preun agent
-/sbin/service cloudstack-agent stop || true
-if [ "$1" == "0" ] ; then
- /sbin/chkconfig --del cloudstack-agent > /dev/null 2>&1 || true
- /sbin/service cloudstack-agent stop > /dev/null 2>&1 || true
-fi
-
-%pre agent
-
-# save old configs if they exist (for upgrade). Otherwise we may lose them
-# when the old packages are erased. There are a lot of properties files here.
-if [ -d "%{_sysconfdir}/cloud" ] ; then
- mv %{_sysconfdir}/cloud %{_sysconfdir}/cloud.rpmsave
-fi
-
-%post agent
-if [ "$1" == "1" ] ; then
- echo "Running %{_bindir}/%{name}-agent-upgrade to update bridge name for upgrade from CloudStack 4.0.x (and before) to CloudStack 4.1 (and later)"
- %{_bindir}/%{name}-agent-upgrade
- if [ ! -d %{_sysconfdir}/libvirt/hooks ] ; then
- mkdir %{_sysconfdir}/libvirt/hooks
- fi
- cp -a ${RPM_BUILD_ROOT}%{_datadir}/%{name}-agent/lib/libvirtqemuhook %{_sysconfdir}/libvirt/hooks/qemu
- /sbin/service libvirtd restart
- /sbin/chkconfig --add cloudstack-agent > /dev/null 2>&1 || true
- /sbin/chkconfig --level 345 cloudstack-agent on > /dev/null 2>&1 || true
-fi
-
-# if saved configs from upgrade exist, copy them over
-if [ -f "%{_sysconfdir}/cloud.rpmsave/agent/agent.properties" ]; then
- mv %{_sysconfdir}/%{name}/agent/agent.properties %{_sysconfdir}/%{name}/agent/agent.properties.rpmnew
- cp -p %{_sysconfdir}/cloud.rpmsave/agent/agent.properties %{_sysconfdir}/%{name}/agent
- # make sure we only do this on the first install of this RPM, don't want to overwrite on a reinstall
- mv %{_sysconfdir}/cloud.rpmsave/agent/agent.properties %{_sysconfdir}/cloud.rpmsave/agent/agent.properties.rpmsave
-fi
-
-%preun usage
-/sbin/service cloudstack-usage stop || true
-if [ "$1" == "0" ] ; then
- /sbin/chkconfig --del cloudstack-usage > /dev/null 2>&1 || true
- /sbin/service cloudstack-usage stop > /dev/null 2>&1 || true
-fi
-
-%post usage
-if [ -f "%{_sysconfdir}/%{name}/management/db.properties" ]; then
- echo Replacing db.properties with management server db.properties
- rm -f %{_sysconfdir}/%{name}/usage/db.properties
- ln -s %{_sysconfdir}/%{name}/management/db.properties %{_sysconfdir}/%{name}/usage/db.properties
- /sbin/chkconfig --add cloudstack-usage > /dev/null 2>&1 || true
- /sbin/chkconfig --level 345 cloudstack-usage on > /dev/null 2>&1 || true
-fi
-
-if [ -f "%{_sysconfdir}/%{name}/management/key" ]; then
- echo Replacing key with management server key
- rm -f %{_sysconfdir}/%{name}/usage/key
- ln -s %{_sysconfdir}/%{name}/management/key %{_sysconfdir}/%{name}/usage/key
-fi
-
-#No default permission as the permission setup is complex
-%files management
-%defattr(-,root,root,-)
-%dir %attr(0770,root,cloud) %{_sysconfdir}/%{name}/management/Catalina
-%dir %attr(0770,root,cloud) %{_sysconfdir}/%{name}/management/Catalina/localhost
-%dir %attr(0770,root,cloud) %{_sysconfdir}/%{name}/management/Catalina/localhost/client
-%dir %{_datadir}/%{name}-management
-%dir %attr(0770,root,cloud) %{_localstatedir}/%{name}/mnt
-%dir %attr(0770,cloud,cloud) %{_localstatedir}/%{name}/management
-%dir %attr(0770,root,cloud) %{_localstatedir}/cache/%{name}/management
-%dir %attr(0770,root,cloud) %{_localstatedir}/cache/%{name}/management/work
-%dir %attr(0770,root,cloud) %{_localstatedir}/cache/%{name}/management/temp
-%dir %attr(0770,root,cloud) %{_localstatedir}/log/%{name}/management
-%config(noreplace) %{_sysconfdir}/sysconfig/%{name}-management
-%config(noreplace) %attr(0640,root,cloud) %{_sysconfdir}/%{name}/management/db.properties
-%config(noreplace) %{_sysconfdir}/%{name}/management/log4j-cloud.xml
-%config(noreplace) %{_sysconfdir}/%{name}/management/tomcat6-nonssl.conf
-%config(noreplace) %{_sysconfdir}/%{name}/management/tomcat6-ssl.conf
-%config(noreplace) %{_sysconfdir}/%{name}/management/Catalina/localhost/client/context.xml
-%config(noreplace) %{_sysconfdir}/%{name}/management/catalina.policy
-%config(noreplace) %{_sysconfdir}/%{name}/management/catalina.properties
-%config(noreplace) %{_sysconfdir}/%{name}/management/classpath.conf
-%config(noreplace) %{_sysconfdir}/%{name}/management/server-nonssl.xml
-%config(noreplace) %{_sysconfdir}/%{name}/management/server-ssl.xml
-%config(noreplace) %{_sysconfdir}/%{name}/management/tomcat-users.xml
-%config(noreplace) %{_sysconfdir}/%{name}/management/web.xml
-%config(noreplace) %{_sysconfdir}/%{name}/management/environment.properties
-%config(noreplace) %{_sysconfdir}/%{name}/management/java.security.ciphers
-%config(noreplace) %{_sysconfdir}/%{name}/management/commons-logging.properties
-%attr(0755,root,root) %{_initrddir}/%{name}-management
-%attr(0755,root,root) %{_initrddir}/tomcat.sh
-
-%attr(0755,root,root) %{_bindir}/%{name}-setup-management
-%attr(0755,root,root) %{_bindir}/%{name}-update-xenserver-licenses
-%{_datadir}/%{name}-management/webapps
-%{_datadir}/%{name}-management/bin
-%{_datadir}/%{name}-management/conf
-%{_datadir}/%{name}-management/lib
-%{_datadir}/%{name}-management/logs
-%{_datadir}/%{name}-management/temp
-%{_datadir}/%{name}-management/work
-%attr(0755,root,root) %{_bindir}/%{name}-setup-databases
-%attr(0755,root,root) %{_bindir}/%{name}-migrate-databases
-%attr(0755,root,root) %{_bindir}/%{name}-set-guest-password
-%attr(0755,root,root) %{_bindir}/%{name}-set-guest-sshkey
-%attr(0755,root,root) %{_bindir}/%{name}-sysvmadm
-%attr(0755,root,root) %{_bindir}/%{name}-setup-encryption
-%{_datadir}/%{name}-management/setup/*.sql
-%{_datadir}/%{name}-management/setup/db/*.sql
-%{_datadir}/%{name}-management/setup/*.sh
-%{_datadir}/%{name}-management/setup/server-setup.xml
-%attr(0755,root,root) %{_bindir}/%{name}-external-ipallocator.py
-%attr(0755,root,root) %{_initrddir}/%{name}-ipallocator
-%dir %attr(0770,root,root) %{_localstatedir}/log/%{name}/ipallocator
-%{_defaultdocdir}/%{name}-management-%{version}/LICENSE
-%{_defaultdocdir}/%{name}-management-%{version}/NOTICE
-%attr(0644,cloud,cloud) %{_localstatedir}/log/%{name}/management/catalina.out
-%attr(0644,root,root) %{_sysconfdir}/logrotate.d/%{name}-catalina
-
-%files agent
-%attr(0755,root,root) %{_bindir}/%{name}-setup-agent
-%attr(0755,root,root) %{_bindir}/%{name}-agent-upgrade
-%attr(0755,root,root) %{_bindir}/%{name}-ssh
-%attr(0755,root,root) %{_sysconfdir}/init.d/%{name}-agent
-%attr(0644,root,root) %{_sysconfdir}/profile.d/%{name}-agent-profile.sh
-%attr(0644,root,root) %{_sysconfdir}/logrotate.d/%{name}-agent
-%attr(0755,root,root) %{_datadir}/%{name}-common/scripts/network/cisco
-%config(noreplace) %{_sysconfdir}/%{name}/agent
-%dir %{_localstatedir}/log/%{name}/agent
-%attr(0644,root,root) %{_datadir}/%{name}-agent/lib/*.jar
-%attr(0755,root,root) %{_datadir}/%{name}-agent/lib/libvirtqemuhook
-%dir %{_datadir}/%{name}-agent/plugins
-%{_defaultdocdir}/%{name}-agent-%{version}/LICENSE
-%{_defaultdocdir}/%{name}-agent-%{version}/NOTICE
-
-%files common
-%dir %attr(0755,root,root) %{python_sitearch}/cloudutils
-%dir %attr(0755,root,root) %{_datadir}/%{name}-common/vms
-%attr(0755,root,root) %{_datadir}/%{name}-common/scripts
-%attr(0755,root,root) /usr/bin/cloudstack-sccs
-%attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso
-%attr(0644,root,root) %{python_sitearch}/cloud_utils.py
-%attr(0644,root,root) %{python_sitearch}/cloud_utils.pyc
-%attr(0644,root,root) %{python_sitearch}/cloudutils/*
-%attr(0644, root, root) %{_datadir}/%{name}-common/lib/jasypt-1.9.2.jar
-%{_defaultdocdir}/%{name}-common-%{version}/LICENSE
-%{_defaultdocdir}/%{name}-common-%{version}/NOTICE
-
-%files usage
-%attr(0755,root,root) %{_sysconfdir}/init.d/%{name}-usage
-%attr(0644,root,root) %{_datadir}/%{name}-usage/*.jar
-%attr(0644,root,root) %{_datadir}/%{name}-usage/lib/*.jar
-%dir %attr(0770,root,cloud) %{_localstatedir}/log/%{name}/usage
-%attr(0644,root,root) %{_sysconfdir}/%{name}/usage/db.properties
-%attr(0644,root,root) %{_sysconfdir}/%{name}/usage/log4j-cloud.xml
-%{_defaultdocdir}/%{name}-usage-%{version}/LICENSE
-%{_defaultdocdir}/%{name}-usage-%{version}/NOTICE
-
-%files cli
-%attr(0644,root,root) %{python_sitearch}/cloudapis.py
-%attr(0644,root,root) %{python_sitearch}/cloudtool/__init__.py
-%attr(0644,root,root) %{python_sitearch}/cloudtool/utils.py
-%{_defaultdocdir}/%{name}-cli-%{version}/LICENSE
-%{_defaultdocdir}/%{name}-cli-%{version}/NOTICE
-
-%if "%{_ossnoss}" == "noredist"
-%files mysql-ha
-%defattr(0644,cloud,cloud,0755)
-%attr(0644,root,root) %{_datadir}/%{name}-mysql-ha/lib/*
-%{_defaultdocdir}/%{name}-mysql-ha-%{version}/LICENSE
-%{_defaultdocdir}/%{name}-mysql-ha-%{version}/NOTICE
-%endif
-
-%files baremetal-agent
-%attr(0755,root,root) %{_bindir}/cloudstack-setup-baremetal
-
-%changelog
-* Thu Apr 30 2015 Rohit Yadav <bh...@apache.org> 4.6.0
-- Remove awsapi package
-
-* Fri Jul 04 2014 Hugo Trippaers <hu...@apache.org> 4.5.0
-- Add a package for the mysql ha module
-
-* Wed Oct 03 2012 Hugo Trippaers <hu...@apache.org> 4.1.0
-- new style spec file
diff --git a/packaging/fedora21/cloudstack-agent.te b/packaging/fedora21/cloudstack-agent.te
deleted file mode 100644
index 4259e173a46..00000000000
--- a/packaging/fedora21/cloudstack-agent.te
+++ /dev/null
@@ -1,33 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-module cloudstack-agent 1.0;
-
-require {
- type nfs_t;
- type system_conf_t;
- type mount_t;
- type qemu_t;
- class file unlink;
- class filesystem getattr;
-}
-
-#============= mount_t ==============
-allow mount_t system_conf_t:file unlink;
-
-#============= qemu_t ==============
-allow qemu_t nfs_t:filesystem getattr;
diff --git a/packaging/fedora21/replace.properties b/packaging/fedora21/replace.properties
deleted file mode 100644
index bdf6e223b59..00000000000
--- a/packaging/fedora21/replace.properties
+++ /dev/null
@@ -1,59 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-DBUSER=cloud
-DBPW=cloud
-DBROOTPW=
-MSLOG=vmops.log
-APISERVERLOG=api.log
-DBHOST=localhost
-DBDRIVER=jdbc:mysql
-COMPONENTS-SPEC=components-premium.xml
-REMOTEHOST=localhost
-AGENTCLASSPATH=
-AGENTLOG=/var/log/cloudstack/agent/agent.log
-AGENTLOGDIR=/var/log/cloudstack/agent/
-AGENTSYSCONFDIR=/etc/cloudstack/agent
-APISERVERLOG=/var/log/cloudstack/management/apilog.log
-BINDIR=/usr/bin
-COMMONLIBDIR=/usr/share/cloudstack-common
-CONFIGUREVARS=
-DEPSCLASSPATH=
-DOCDIR=
-IPALOCATORLOG=/var/log/cloudstack/management/ipallocator.log
-JAVADIR=/usr/share/java
-LIBEXECDIR=/usr/libexec
-LOCKDIR=/var/lock
-MSCLASSPATH=
-MSCONF=/etc/cloudstack/management
-MSENVIRON=/usr/share/cloudstack-management
-MSLOG=/var/log/cloudstack/management/management-server.log
-MSLOGDIR=/var/log/cloudstack/management/
-MSMNTDIR=/var/cloudstack/mnt
-MSUSER=cloud
-PIDDIR=/var/run
-PLUGINJAVADIR=/usr/share/cloudstack-management/plugin
-PREMIUMJAVADIR=/usr/share/cloudstack-management/premium
-PYTHONDIR=/usr/lib/python2.6/site-packages/
-SERVERSYSCONFDIR=/etc/sysconfig
-SETUPDATADIR=/usr/share/cloudstack-management/setup
-SYSCONFDIR=/etc/sysconfig
-SYSTEMCLASSPATH=
-SYSTEMJARS=
-USAGECLASSPATH=
-USAGELOG=/var/log/cloudstack/usage/usage.log
-USAGESYSCONFDIR=/etc/sysconfig
diff --git a/packaging/systemd/cloudstack-management.default b/packaging/systemd/cloudstack-management.default
index 6e5fcf9d8d6..fbdb25634a1 100644
--- a/packaging/systemd/cloudstack-management.default
+++ b/packaging/systemd/cloudstack-management.default
@@ -5,9 +5,9 @@
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
-#
+#
# http://www.apache.org/licenses/LICENSE-2.0
-#
+#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -15,35 +15,21 @@
# specific language governing permissions and limitations
# under the License.
-# Required for a tocmat cloned service
-SERVICE_NAME=cloudstack-management
-
# Where your java installation lives
#JAVA_HOME="/usr/lib/jvm/java"
-# Where your cloudstack-management installation lives
-CATALINA_BASE="/usr/share/cloudstack-management"
-CATALINA_HOME="/usr/share/cloudstack-management"
-JASPER_HOME="/usr/share/cloudstack-management"
-CATALINA_TMPDIR="/usr/share/cloudstack-management/temp"
-
-
-if [ -r "/etc/cloudstack/management/cloudmanagementserver.keystore" ] ; then
- JAVA_OPTS="-Djava.awt.headless=true -Dcom.sun.management.jmxremote=false -Xmx2g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/cloudstack/management/ -XX:PermSize=512M -XX:MaxPermSize=800m -Djavax.net.ssl.trustStore=/etc/cloudstack/management/cloudmanagementserver.keystore -Djavax.net.ssl.trustStorePassword=vmops.com "
+if [ -r "/etc/cloudstack/management/cloud.jks" ] ; then
+ JAVA_OPTS="-Djava.awt.headless=true -Dcom.sun.management.jmxremote=false -Xmx2g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/cloudstack/management/ -XX:PermSize=512M -XX:MaxPermSize=800m -Djavax.net.ssl.trustStore=/etc/cloudstack/management/cloud.jks -Djavax.net.ssl.trustStorePassword=vmops.com -Djava.security.properties=/etc/cloudstack/management/java.security.ciphers "
else
- JAVA_OPTS="-Djava.awt.headless=true -Dcom.sun.management.jmxremote=false -Xmx2g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/cloudstack/management/ -XX:PermSize=512M -XX:MaxPermSize=800m"
+ JAVA_OPTS="-Djava.awt.headless=true -Dcom.sun.management.jmxremote=false -Xmx2g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/cloudstack/management/ -XX:PermSize=512M -XX:MaxPermSize=800m -Djava.security.properties=/etc/cloudstack/management/java.security.ciphers "
fi
-TOMCAT_USER="cloud"
-
-SECURITY_MANAGER="false"
-
-SHUTDOWN_WAIT="30"
+CLOUDSTACK_USER="cloud"
-SHUTDOWN_VERBOSE="false"
+CLOUDSTACK_PID="/var/run/cloudstack-management.pid"
-# Set the TOMCAT_PID location
-CATALINA_PID="/var/run/cloudstack-management.pid"
+LOGDIR="/var/log/cloudstack/management"
-CLASSPATH=/etc/cloudstack/management:/usr/share/cloudstack-common:/usr/share/cloudstack-management/setup
+CLASSPATH="/etc/cloudstack/management:/usr/share/cloudstack-common:/usr/share/cloudstack-management/setup:/usr/share/cloudstack-management:/usr/share/java/mysql-connector-java.jar:/usr/share/java/commons-daemon.jar"
+BOOTSTRAP_CLASS=org.apache.cloudstack.ServerDaemon
diff --git a/packaging/systemd/cloudstack-management.default.ubuntu b/packaging/systemd/cloudstack-management.default.ubuntu
deleted file mode 100644
index 0087495dbcd..00000000000
--- a/packaging/systemd/cloudstack-management.default.ubuntu
+++ /dev/null
@@ -1,50 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# Required for a tocmat cloned service
-SERVICE_NAME=cloudstack-management
-
-# Where your java installation lives
-#JAVA_HOME="/usr/lib/jvm/java"
-
-# Where your cloudstack-management installation lives
-CATALINA_BASE="/usr/share/cloudstack-management"
-CATALINA_HOME="/usr/share/cloudstack-management"
-JASPER_HOME="/usr/share/cloudstack-management"
-CATALINA_TMPDIR="/usr/share/cloudstack-management/temp"
-
-
-if [ -r "/etc/cloudstack/management/cloudmanagementserver.keystore" ] ; then
- JAVA_OPTS="-Djava.awt.headless=true -Dcom.sun.management.jmxremote=false -Xmx2g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/cloudstack/management/ -XX:PermSize=512M -XX:MaxPermSize=800m -Djavax.net.ssl.trustStore=/etc/cloudstack/management/cloudmanagementserver.keystore -Djavax.net.ssl.trustStorePassword=vmops.com "
-else
- JAVA_OPTS="-Djava.awt.headless=true -Dcom.sun.management.jmxremote=false -Xmx2g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/cloudstack/management/ -XX:PermSize=512M -XX:MaxPermSize=800m"
-fi
-
-TOMCAT_USER="cloud"
-
-SECURITY_MANAGER="false"
-
-SHUTDOWN_WAIT="30"
-
-SHUTDOWN_VERBOSE="false"
-
-# Set the TOMCAT_PID location
-CATALINA_PID="/var/run/cloudstack-management.pid"
-
-CLASSPATH=/usr/share/java/commons-daemon.jar:/usr/share/cloudstack-management/bin/bootstrap.jar:/usr/share/tomcat7/bin/tomcat-juli.jar:/etc/cloudstack/management:/usr/share/cloudstack-common:/usr/share/cloudstack-management/setup
-
-BOOTSTRAP_CLASS=org.apache.catalina.startup.Bootstrap
diff --git a/packaging/systemd/cloudstack-management.service b/packaging/systemd/cloudstack-management.service
index c1ede4bed80..afcea8ca6f6 100644
--- a/packaging/systemd/cloudstack-management.service
+++ b/packaging/systemd/cloudstack-management.service
@@ -16,8 +16,6 @@
# under the License.
# Systemd unit file for CloudStack Management server
-#
-# clone tomcat service, see /usr/lib/systemd/system/tomcat.service
[Unit]
Description=CloudStack Management Server
@@ -25,16 +23,14 @@ After=syslog.target network.target
[Service]
UMask=0022
-Type=simple
-EnvironmentFile=/etc/tomcat/tomcat.conf
+Type=forking
Environment="NAME=cloudstack-management"
-EnvironmentFile=-/etc/default/cloudstack-management
-ExecStart=/usr/libexec/tomcat/server start
-ExecStop=/usr/libexec/tomcat/server stop
+EnvironmentFile=/etc/default/cloudstack-management
+ExecStartPre=/bin/bash -c "/bin/systemctl set-environment JAVA_HOME=$( readlink -f $( which java ) | sed s:bin/.*$:: )"
+ExecStartPre=/bin/bash -c "/bin/systemctl set-environment JARS=$(ls /usr/share/cloudstack-management/lib/*.jar | tr '\n' ':' | sed s'/.$//')"
+ExecStart=/usr/bin/jsvc -home "${JAVA_HOME}" -user "${CLOUDSTACK_USER}" -cp "${JARS}:${CLASSPATH}" -errfile ${LOGDIR}/${NAME}.err -cwd ${LOGDIR} -pidfile "${CLOUDSTACK_PID}" ${JAVA_OPTS} "${BOOTSTRAP_CLASS}"
+ExecStop=/usr/bin/jsvc -cp "$JARS:$CLASSPATH" -pidfile "$CLOUDSTACK_PID" -stop "$BOOTSTRAP_CLASS"
SuccessExitStatus=143
-User=cloud
-Group=cloud
[Install]
WantedBy=multi-user.target
-
diff --git a/packaging/systemd/cloudstack-management.service.ubuntu b/packaging/systemd/cloudstack-management.service.ubuntu
deleted file mode 100644
index 2fd77676399..00000000000
--- a/packaging/systemd/cloudstack-management.service.ubuntu
+++ /dev/null
@@ -1,40 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# Systemd unit file for CloudStack Management server
-#
-# clone tomcat service, see /usr/lib/systemd/system/tomcat.service
-
-[Unit]
-Description=CloudStack Management Server
-After=syslog.target network.target
-
-[Service]
-UMask=0022
-Type=forking
-Environment="NAME=cloudstack-management"
-EnvironmentFile=-/etc/default/cloudstack-management
-ExecStartPre=/bin/bash -c "/bin/systemctl set-environment JAVA_HOME=$( readlink -f $( which java ) | sed s:bin/.*$:: )"
-ExecStart=/usr/bin/jsvc -user "${TOMCAT_USER}" -cp "$CLASSPATH" \
- -outfile SYSLOG -errfile SYSLOG \
- -pidfile "${CATALINA_PID}" ${JAVA_OPTS} \
- -Dcatalina.base="${CATALINA_BASE}" -Dcatalina.home="${CATALINA_HOME}" -Djava.io.tmpdir="${CATALINA_TMPDIR}" "${BOOTSTRAP_CLASS}"
-ExecStop=/usr/bin/jsvc -cp "$CLASSPATH" -pidfile "$CATALINA_PID" \
- -stop "$BOOTSTRAP_CLASS"
-
-[Install]
-WantedBy=multi-user.target
diff --git a/plugins/acl/dynamic-role-based/pom.xml b/plugins/acl/dynamic-role-based/pom.xml
index f6ceffe62d6..760645bd715 100644
--- a/plugins/acl/dynamic-role-based/pom.xml
+++ b/plugins/acl/dynamic-role-based/pom.xml
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
</project>
diff --git a/plugins/acl/static-role-based/pom.xml b/plugins/acl/static-role-based/pom.xml
index a05454cd789..b3f9ffe151b 100644
--- a/plugins/acl/static-role-based/pom.xml
+++ b/plugins/acl/static-role-based/pom.xml
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
</project>
diff --git a/plugins/affinity-group-processors/explicit-dedication/pom.xml b/plugins/affinity-group-processors/explicit-dedication/pom.xml
index 4a0b6c6e932..e1389e46ea3 100644
--- a/plugins/affinity-group-processors/explicit-dedication/pom.xml
+++ b/plugins/affinity-group-processors/explicit-dedication/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<build>
diff --git a/plugins/affinity-group-processors/host-anti-affinity/pom.xml b/plugins/affinity-group-processors/host-anti-affinity/pom.xml
index 463110d6b8b..b5eb906585c 100644
--- a/plugins/affinity-group-processors/host-anti-affinity/pom.xml
+++ b/plugins/affinity-group-processors/host-anti-affinity/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<build>
diff --git a/plugins/alert-handlers/snmp-alerts/pom.xml b/plugins/alert-handlers/snmp-alerts/pom.xml
index fd20c524336..95d8833a5e8 100644
--- a/plugins/alert-handlers/snmp-alerts/pom.xml
+++ b/plugins/alert-handlers/snmp-alerts/pom.xml
@@ -22,7 +22,7 @@
<parent>
<artifactId>cloudstack-plugins</artifactId>
<groupId>org.apache.cloudstack</groupId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/plugins/alert-handlers/syslog-alerts/pom.xml b/plugins/alert-handlers/syslog-alerts/pom.xml
index a019cef8204..1b5858460a0 100644
--- a/plugins/alert-handlers/syslog-alerts/pom.xml
+++ b/plugins/alert-handlers/syslog-alerts/pom.xml
@@ -22,7 +22,7 @@
<parent>
<artifactId>cloudstack-plugins</artifactId>
<groupId>org.apache.cloudstack</groupId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/plugins/api/discovery/pom.xml b/plugins/api/discovery/pom.xml
index daf56ef4fa6..05ba4d6b240 100644
--- a/plugins/api/discovery/pom.xml
+++ b/plugins/api/discovery/pom.xml
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/api/rate-limit/pom.xml b/plugins/api/rate-limit/pom.xml
index 41a1a47a406..e4177709a79 100644
--- a/plugins/api/rate-limit/pom.xml
+++ b/plugins/api/rate-limit/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<build>
diff --git a/plugins/api/solidfire-intg-test/pom.xml b/plugins/api/solidfire-intg-test/pom.xml
index c7dd5971c5e..0c1638f1dec 100644
--- a/plugins/api/solidfire-intg-test/pom.xml
+++ b/plugins/api/solidfire-intg-test/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/solidfire/SolidFireIntegrationTestManagerImpl.java b/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/solidfire/SolidFireIntegrationTestManagerImpl.java
index ff6e72cb29a..ba873aad124 100644
--- a/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/solidfire/SolidFireIntegrationTestManagerImpl.java
+++ b/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/solidfire/SolidFireIntegrationTestManagerImpl.java
@@ -16,21 +16,20 @@
// under the License.
package org.apache.cloudstack.solidfire;
-import javax.inject.Inject;
-
-import org.apache.cloudstack.storage.datastore.util.SolidFireUtil;
-import org.apache.cloudstack.util.solidfire.SolidFireIntegrationTestUtil;
-import org.springframework.stereotype.Component;
-
import com.cloud.dc.ClusterDetailsDao;
import com.cloud.dc.ClusterDetailsVO;
import com.cloud.storage.VolumeDetailVO;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.dao.VolumeDetailsDao;
-import com.cloud.user.AccountDetailsDao;
import com.cloud.user.AccountDetailVO;
+import com.cloud.user.AccountDetailsDao;
import com.cloud.utils.exception.CloudRuntimeException;
+import org.apache.cloudstack.storage.datastore.util.SolidFireUtil;
+import org.apache.cloudstack.util.solidfire.SolidFireIntegrationTestUtil;
+import org.springframework.stereotype.Component;
+
+import javax.inject.Inject;
@Component
public class SolidFireIntegrationTestManagerImpl implements SolidFireIntegrationTestManager {
@@ -47,6 +46,9 @@ public long getSolidFireAccountId(String csAccountUuid, String storagePoolUuid)
long storagePoolId = util.getStoragePoolIdForStoragePoolUuid(storagePoolUuid);
AccountDetailVO accountDetail = accountDetailsDao.findDetail(csAccountId, SolidFireUtil.getAccountKey(storagePoolId));
+ if (accountDetail == null){
+ throw new CloudRuntimeException("Unable to find SF account for storage " + storagePoolUuid + " for CS account " + csAccountUuid);
+ }
String sfAccountId = accountDetail.getValue();
return Long.parseLong(sfAccountId);
diff --git a/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/util/solidfire/SolidFireIntegrationTestUtil.java b/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/util/solidfire/SolidFireIntegrationTestUtil.java
index 307e8c59691..427af111ed0 100644
--- a/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/util/solidfire/SolidFireIntegrationTestUtil.java
+++ b/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/util/solidfire/SolidFireIntegrationTestUtil.java
@@ -16,15 +16,6 @@
// under the License.
package org.apache.cloudstack.util.solidfire;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.inject.Inject;
-
-import org.apache.cloudstack.api.response.solidfire.ApiVolumeSnapshotDetailsResponse;
-import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
-import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
-
import com.cloud.dc.ClusterVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.storage.SnapshotVO;
@@ -35,6 +26,14 @@
import com.cloud.storage.dao.VolumeDao;
import com.cloud.user.Account;
import com.cloud.user.dao.AccountDao;
+import com.cloud.utils.exception.CloudRuntimeException;
+import org.apache.cloudstack.api.response.solidfire.ApiVolumeSnapshotDetailsResponse;
+import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
+
+import javax.inject.Inject;
+import java.util.ArrayList;
+import java.util.List;
public class SolidFireIntegrationTestUtil {
@Inject private AccountDao accountDao;
@@ -48,48 +47,70 @@ private SolidFireIntegrationTestUtil() {}
public long getAccountIdForAccountUuid(String accountUuid) {
Account account = accountDao.findByUuid(accountUuid);
-
+ if (account == null){
+ throw new CloudRuntimeException("Unable to find Account for ID: " + accountUuid);
+ }
return account.getAccountId();
}
public long getAccountIdForVolumeUuid(String volumeUuid) {
VolumeVO volume = volumeDao.findByUuid(volumeUuid);
+ if (volume == null){
+ throw new CloudRuntimeException("Unable to find Volume for ID: " + volumeUuid);
+ }
return volume.getAccountId();
}
public long getAccountIdForSnapshotUuid(String snapshotUuid) {
SnapshotVO snapshot = snapshotDao.findByUuid(snapshotUuid);
-
+ if (snapshot == null){
+ throw new CloudRuntimeException("Unable to find Volume for ID: " + snapshotUuid);
+ }
return snapshot.getAccountId();
}
public long getClusterIdForClusterUuid(String clusterUuid) {
ClusterVO cluster = clusterDao.findByUuid(clusterUuid);
+ if (cluster == null){
+ throw new CloudRuntimeException("Unable to find Volume for ID: " + clusterUuid);
+ }
return cluster.getId();
}
public long getStoragePoolIdForStoragePoolUuid(String storagePoolUuid) {
StoragePoolVO storagePool = storagePoolDao.findByUuid(storagePoolUuid);
+ if (storagePool == null){
+ throw new CloudRuntimeException("Unable to find Volume for ID: " + storagePoolUuid);
+ }
return storagePool.getId();
}
public String getPathForVolumeUuid(String volumeUuid) {
VolumeVO volume = volumeDao.findByUuid(volumeUuid);
+ if (volume == null){
+ throw new CloudRuntimeException("Unable to find Volume for ID: " + volumeUuid);
+ }
return volume.getPath();
}
public String getVolume_iScsiName(String volumeUuid) {
VolumeVO volume = volumeDao.findByUuid(volumeUuid);
+ if (volume == null){
+ throw new CloudRuntimeException("Unable to find Volume for ID: " + volumeUuid);
+ }
return volume.get_iScsiName();
}
public List<ApiVolumeSnapshotDetailsResponse> getSnapshotDetails(String snapshotUuid) {
SnapshotVO snapshot = snapshotDao.findByUuid(snapshotUuid);
+ if (snapshot == null){
+ throw new CloudRuntimeException("Unable to find Volume for ID: " + snapshotUuid);
+ }
List<SnapshotDetailsVO> snapshotDetails = snapshotDetailsDao.listDetails(snapshot.getId());
diff --git a/plugins/network-elements/midonet/pom.xml b/plugins/ca/root-ca/pom.xml
similarity index 61%
rename from plugins/network-elements/midonet/pom.xml
rename to plugins/ca/root-ca/pom.xml
index 353a368ca76..e27f4911223 100644
--- a/plugins/network-elements/midonet/pom.xml
+++ b/plugins/ca/root-ca/pom.xml
@@ -18,43 +18,29 @@
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
- <artifactId>cloud-plugin-network-midonet</artifactId>
- <name>Apache CloudStack Plugin - Midokura Midonet</name>
+ <artifactId>cloud-plugin-ca-rootca</artifactId>
+ <name>Apache CloudStack Plugin - Inbuilt Root Certificate Authority</name>
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
-<repositories>
- <repository>
- <id>mido-maven-public-releases</id>
- <name>mido-maven-public-releases</name>
- <url>http://cs-maven.midokura.com/releases</url>
- </repository>
-</repositories>
<dependencies>
- <dependency>
- <groupId>org.midonet</groupId>
- <artifactId>midonet-client</artifactId>
- <version>1.1.0</version>
- </dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
- <artifactId>cloud-plugin-hypervisor-kvm</artifactId>
+ <artifactId>cloud-utils</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
- <groupId>org.codehaus.jackson</groupId>
- <artifactId>jackson-core-asl</artifactId>
- <version>1.9.11</version>
- <scope>runtime</scope>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-api</artifactId>
+ <version>${project.version}</version>
</dependency>
<dependency>
- <groupId>org.codehaus.jackson</groupId>
- <artifactId>jackson-mapper-asl</artifactId>
- <version>1.9.11</version>
- <scope>runtime</scope>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-framework-ca</artifactId>
+ <version>${project.version}</version>
</dependency>
</dependencies>
</project>
diff --git a/packaging/fedora21/tomcat.sh b/plugins/ca/root-ca/resources/META-INF/cloudstack/root-ca/module.properties
similarity index 97%
rename from packaging/fedora21/tomcat.sh
rename to plugins/ca/root-ca/resources/META-INF/cloudstack/root-ca/module.properties
index 76ba7419a53..e086bc03073 100644
--- a/packaging/fedora21/tomcat.sh
+++ b/plugins/ca/root-ca/resources/META-INF/cloudstack/root-ca/module.properties
@@ -14,5 +14,5 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-
-service tomcat start
+name=root-ca
+parent=ca
diff --git a/plugins/network-elements/midonet/resources/META-INF/cloudstack/midonet/spring-midonet-context.xml b/plugins/ca/root-ca/resources/META-INF/cloudstack/root-ca/spring-root-ca-context.xml
similarity index 58%
rename from plugins/network-elements/midonet/resources/META-INF/cloudstack/midonet/spring-midonet-context.xml
rename to plugins/ca/root-ca/resources/META-INF/cloudstack/root-ca/spring-root-ca-context.xml
index 957f079aa75..46503febd7b 100644
--- a/plugins/network-elements/midonet/resources/META-INF/cloudstack/midonet/spring-midonet-context.xml
+++ b/plugins/ca/root-ca/resources/META-INF/cloudstack/root-ca/spring-root-ca-context.xml
@@ -18,20 +18,12 @@
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context.xsd"
- >
+ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
+>
- <bean id="MidoNetGuestNetworkGuru" class="com.cloud.network.guru.MidoNetGuestNetworkGuru">
- <property name="name" value="MidoNetGuestNetworkGuru" />
+ <bean id="rootCAProvider" class="org.apache.cloudstack.ca.provider.RootCAProvider">
+ <property name="name" value="RootCAProvider" />
</bean>
- <bean id="MidoNetElement" class="com.cloud.network.element.MidoNetElement">
- <property name="name" value="MidoNetElement" />
- </bean>
-
+
</beans>
diff --git a/plugins/ca/root-ca/src/org/apache/cloudstack/ca/provider/RootCACustomTrustManager.java b/plugins/ca/root-ca/src/org/apache/cloudstack/ca/provider/RootCACustomTrustManager.java
new file mode 100644
index 00000000000..90f620393ee
--- /dev/null
+++ b/plugins/ca/root-ca/src/org/apache/cloudstack/ca/provider/RootCACustomTrustManager.java
@@ -0,0 +1,146 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ca.provider;
+
+import java.math.BigInteger;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import java.util.List;
+import java.util.Map;
+
+import javax.net.ssl.X509TrustManager;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.certificate.dao.CrlDao;
+import com.google.common.base.Strings;
+
+public final class RootCACustomTrustManager implements X509TrustManager {
+ private static final Logger LOG = Logger.getLogger(RootCACustomTrustManager.class);
+
+ private String clientAddress = "Unknown";
+ private boolean authStrictness = true;
+ private boolean allowExpiredCertificate = true;
+ private CrlDao crlDao;
+ private X509Certificate caCertificate;
+ private Map<String, X509Certificate> activeCertMap;
+
+ public RootCACustomTrustManager(final String clientAddress, final boolean authStrictness, final boolean allowExpiredCertificate, final Map<String, X509Certificate> activeCertMap, final X509Certificate caCertificate, final CrlDao crlDao) {
+ if (!Strings.isNullOrEmpty(clientAddress)) {
+ this.clientAddress = clientAddress.replace("/", "").split(":")[0];
+ }
+ this.authStrictness = authStrictness;
+ this.allowExpiredCertificate = allowExpiredCertificate;
+ this.activeCertMap = activeCertMap;
+ this.caCertificate = caCertificate;
+ this.crlDao = crlDao;
+ }
+
+ private void printCertificateChain(final X509Certificate[] certificates, final String s) throws CertificateException {
+ if (certificates == null) {
+ return;
+ }
+ final StringBuilder builder = new StringBuilder();
+ builder.append("A client/agent attempting connection from address=").append(clientAddress).append(" has presented these certificate(s):");
+ int counter = 1;
+ for (final X509Certificate certificate: certificates) {
+ builder.append("\nCertificate [").append(counter++).append("] :");
+ builder.append(String.format("\n Serial: %x", certificate.getSerialNumber()));
+ builder.append("\n Not Before:" + certificate.getNotBefore());
+ builder.append("\n Not After:" + certificate.getNotAfter());
+ builder.append("\n Signature Algorithm:" + certificate.getSigAlgName());
+ builder.append("\n Version:" + certificate.getVersion());
+ builder.append("\n Subject DN:" + certificate.getSubjectDN());
+ builder.append("\n Issuer DN:" + certificate.getIssuerDN());
+ builder.append("\n Alternative Names:" + certificate.getSubjectAlternativeNames());
+ }
+ LOG.debug(builder.toString());
+ }
+
+ @Override
+ public void checkClientTrusted(final X509Certificate[] certificates, final String s) throws CertificateException {
+ if (LOG.isDebugEnabled()) {
+ printCertificateChain(certificates, s);
+ }
+ if (!authStrictness) {
+ return;
+ }
+ if (certificates == null || certificates.length < 1 || certificates[0] == null) {
+ throw new CertificateException("In strict auth mode, certificate(s) are expected from client:" + clientAddress);
+ }
+ final X509Certificate primaryClientCertificate = certificates[0];
+
+ // Revocation check
+ final BigInteger serialNumber = primaryClientCertificate.getSerialNumber();
+ if (serialNumber == null || crlDao.findBySerial(serialNumber) != null) {
+ final String errorMsg = String.format("Client is using revoked certificate of serial=%x, subject=%s from address=%s",
+ primaryClientCertificate.getSerialNumber(), primaryClientCertificate.getSubjectDN(), clientAddress);
+ LOG.error(errorMsg);
+ throw new CertificateException(errorMsg);
+ }
+
+ // Validity check
+ if (!allowExpiredCertificate) {
+ try {
+ primaryClientCertificate.checkValidity();
+ } catch (final CertificateExpiredException | CertificateNotYetValidException e) {
+ final String errorMsg = String.format("Client certificate has expired with serial=%x, subject=%s from address=%s",
+ primaryClientCertificate.getSerialNumber(), primaryClientCertificate.getSubjectDN(), clientAddress);
+ LOG.error(errorMsg);
+ throw new CertificateException(errorMsg); }
+ }
+
+ // Ownership check
+ boolean certMatchesOwnership = false;
+ if (primaryClientCertificate.getSubjectAlternativeNames() != null) {
+ for (final List<?> list : primaryClientCertificate.getSubjectAlternativeNames()) {
+ if (list != null && list.size() == 2 && list.get(1) instanceof String) {
+ final String alternativeName = (String) list.get(1);
+ if (clientAddress.equals(alternativeName)) {
+ certMatchesOwnership = true;
+ }
+ }
+ }
+ }
+ if (!certMatchesOwnership) {
+ final String errorMsg = "Certificate ownership verification failed for client: " + clientAddress;
+ LOG.error(errorMsg);
+ throw new CertificateException(errorMsg);
+ }
+ if (activeCertMap != null && !Strings.isNullOrEmpty(clientAddress)) {
+ activeCertMap.put(clientAddress, primaryClientCertificate);
+ }
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Client/agent connection from ip=" + clientAddress + " has been validated and trusted.");
+ }
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ if (!authStrictness) {
+ return null;
+ }
+ return new X509Certificate[]{caCertificate};
+ }
+}
diff --git a/plugins/ca/root-ca/src/org/apache/cloudstack/ca/provider/RootCAProvider.java b/plugins/ca/root-ca/src/org/apache/cloudstack/ca/provider/RootCAProvider.java
new file mode 100644
index 00000000000..4a3585ac4e2
--- /dev/null
+++ b/plugins/ca/root-ca/src/org/apache/cloudstack/ca/provider/RootCAProvider.java
@@ -0,0 +1,413 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ca.provider;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.KeyManagementException;
+import java.security.KeyPair;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.security.SignatureException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.security.spec.InvalidKeySpecException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+
+import org.apache.cloudstack.ca.CAManager;
+import org.apache.cloudstack.framework.ca.CAProvider;
+import org.apache.cloudstack.framework.ca.Certificate;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.Configurable;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.utils.security.CertUtils;
+import org.apache.cloudstack.utils.security.KeyStoreUtils;
+import org.apache.log4j.Logger;
+import org.bouncycastle.jce.PKCS10CertificationRequest;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.util.io.pem.PemObject;
+import org.bouncycastle.util.io.pem.PemReader;
+
+import com.cloud.certificate.dao.CrlDao;
+import com.cloud.utils.component.AdapterBase;
+import com.cloud.utils.db.GlobalLock;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.net.NetUtils;
+import com.google.common.base.Strings;
+
+public final class RootCAProvider extends AdapterBase implements CAProvider, Configurable {
+ private static final Logger LOG = Logger.getLogger(RootCAProvider.class);
+
+ public static final Integer caValidityYears = 30;
+ public static final String caAlias = "root";
+ public static final String managementAlias = "management";
+
+ private static KeyPair caKeyPair = null;
+ private static X509Certificate caCertificate = null;
+ private static KeyStore managementKeyStore = null;
+
+ @Inject
+ private ConfigurationDao configDao;
+ @Inject
+ private CrlDao crlDao;
+
+ ////////////////////////////////////////////////////
+ /////////////// Root CA Settings ///////////////////
+ ////////////////////////////////////////////////////
+
+ private static ConfigKey<String> rootCAPrivateKey = new ConfigKey<>("Hidden", String.class,
+ "ca.plugin.root.private.key",
+ null,
+ "The ROOT CA private key.", true);
+
+ private static ConfigKey<String> rootCAPublicKey = new ConfigKey<>("Hidden", String.class,
+ "ca.plugin.root.public.key",
+ null,
+ "The ROOT CA public key.", true);
+
+ private static ConfigKey<String> rootCACertificate = new ConfigKey<>("Hidden", String.class,
+ "ca.plugin.root.ca.certificate",
+ null,
+ "The ROOT CA certificate.", true);
+
+ private static ConfigKey<String> rootCAIssuerDN = new ConfigKey<>("Advanced", String.class,
+ "ca.plugin.root.issuer.dn",
+ "CN=ca.cloudstack.apache.org",
+ "The ROOT CA issuer distinguished name.", true);
+
+ protected static ConfigKey<Boolean> rootCAAuthStrictness = new ConfigKey<>("Advanced", Boolean.class,
+ "ca.plugin.root.auth.strictness",
+ "false",
+ "Set client authentication strictness, setting to true will enforce and require client certificate for authentication in applicable CA providers.", true);
+
+ private static ConfigKey<Boolean> rootCAAllowExpiredCert = new ConfigKey<>("Advanced", Boolean.class,
+ "ca.plugin.root.allow.expired.cert",
+ "true",
+ "When set to true, it will allow expired client certificate during SSL handshake.", true);
+
+
+ ///////////////////////////////////////////////////////////
+ /////////////// Root CA Private Methods ///////////////////
+ ///////////////////////////////////////////////////////////
+
+ private Certificate generateCertificate(final List<String> domainNames, final List<String> ipAddresses, final int validityDays) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, CertificateException, SignatureException, IOException, OperatorCreationException {
+ if (domainNames == null || domainNames.size() < 1 || Strings.isNullOrEmpty(domainNames.get(0))) {
+ throw new CloudRuntimeException("No domain name is specified, cannot generate certificate");
+ }
+ final String subject = "CN=" + domainNames.get(0);
+
+ final KeyPair keyPair = CertUtils.generateRandomKeyPair(CAManager.CertKeySize.value());
+ final X509Certificate clientCertificate = CertUtils.generateV3Certificate(
+ caCertificate, caKeyPair, keyPair.getPublic(),
+ subject, CAManager.CertSignatureAlgorithm.value(),
+ validityDays, domainNames, ipAddresses);
+ return new Certificate(clientCertificate, keyPair.getPrivate(), Collections.singletonList(caCertificate));
+ }
+
+ private Certificate generateCertificateUsingCsr(final String csr, final List<String> domainNames, final List<String> ipAddresses, final int validityDays) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, CertificateException, SignatureException, IOException, OperatorCreationException {
+ PemObject pemObject = null;
+
+ try {
+ final PemReader pemReader = new PemReader(new StringReader(csr));
+ pemObject = pemReader.readPemObject();
+ } catch (IOException e) {
+ LOG.error("Failed to read provided CSR string as a PEM object", e);
+ }
+
+ if (pemObject == null) {
+ throw new CloudRuntimeException("Unable to read/process CSR: " + csr);
+ }
+
+ final PKCS10CertificationRequest request = new PKCS10CertificationRequest(pemObject.getContent());
+
+ final String subject = request.getCertificationRequestInfo().getSubject().toString();
+ final X509Certificate clientCertificate = CertUtils.generateV3Certificate(
+ caCertificate, caKeyPair, request.getPublicKey(),
+ subject, CAManager.CertSignatureAlgorithm.value(),
+ validityDays, domainNames, ipAddresses);
+ return new Certificate(clientCertificate, null, Collections.singletonList(caCertificate));
+ }
+
+ ////////////////////////////////////////////////////////
+ /////////////// Root CA API Handlers ///////////////////
+ ////////////////////////////////////////////////////////
+
+ @Override
+ public boolean canProvisionCertificates() {
+ return true;
+ }
+
+ @Override
+ public List<X509Certificate> getCaCertificate() {
+ return Collections.singletonList(caCertificate);
+ }
+
+ @Override
+ public Certificate issueCertificate(final List<String> domainNames, final List<String> ipAddresses, final int validityDays) {
+ try {
+ return generateCertificate(domainNames, ipAddresses, validityDays);
+ } catch (final CertificateException | IOException | SignatureException | NoSuchAlgorithmException | NoSuchProviderException | InvalidKeyException | OperatorCreationException e) {
+ LOG.error("Failed to create client certificate, due to: ", e);
+ throw new CloudRuntimeException("Failed to generate certificate due to:" + e.getMessage());
+ }
+ }
+
+ @Override
+ public Certificate issueCertificate(final String csr, final List<String> domainNames, final List<String> ipAddresses, final int validityDays) {
+ try {
+ return generateCertificateUsingCsr(csr, domainNames, ipAddresses, validityDays);
+ } catch (final CertificateException | IOException | SignatureException | NoSuchAlgorithmException | NoSuchProviderException | InvalidKeyException | OperatorCreationException e) {
+ LOG.error("Failed to generate certificate from CSR: ", e);
+ throw new CloudRuntimeException("Failed to generate certificate using CSR due to:" + e.getMessage());
+ }
+ }
+
+ @Override
+ public boolean revokeCertificate(final BigInteger certSerial, final String certCn) {
+ return true;
+ }
+
+ ////////////////////////////////////////////////////////////
+ /////////////// Root CA Trust Management ///////////////////
+ ////////////////////////////////////////////////////////////
+
+ private KeyStore getCaKeyStore() throws CertificateException, NoSuchAlgorithmException, IOException, KeyStoreException {
+ final KeyStore ks = KeyStore.getInstance("JKS");
+ ks.load(null, null);
+ if (caKeyPair != null && caCertificate != null) {
+ ks.setKeyEntry(caAlias, caKeyPair.getPrivate(), getKeyStorePassphrase(), new X509Certificate[]{caCertificate});
+ } else {
+ return null;
+ }
+ return ks;
+ }
+
+ @Override
+ public SSLEngine createSSLEngine(final SSLContext sslContext, final String remoteAddress, final Map<String, X509Certificate> certMap) throws KeyManagementException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException {
+ final KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+ final TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
+
+ final KeyStore ks = getCaKeyStore();
+ kmf.init(ks, getKeyStorePassphrase());
+ tmf.init(ks);
+
+ final boolean authStrictness = rootCAAuthStrictness.value();
+ final boolean allowExpiredCertificate = rootCAAllowExpiredCert.value();
+
+ TrustManager[] tms = new TrustManager[]{new RootCACustomTrustManager(remoteAddress, authStrictness, allowExpiredCertificate, certMap, caCertificate, crlDao)};
+ sslContext.init(kmf.getKeyManagers(), tms, new SecureRandom());
+ final SSLEngine sslEngine = sslContext.createSSLEngine();
+ sslEngine.setNeedClientAuth(authStrictness);
+ return sslEngine;
+ }
+
+ @Override
+ public KeyStore getManagementKeyStore() throws KeyStoreException {
+ return managementKeyStore;
+ }
+
+ @Override
+ public char[] getKeyStorePassphrase() {
+ return KeyStoreUtils.defaultKeystorePassphrase;
+ }
+
+ /////////////////////////////////////////////////
+ /////////////// Root CA Setup ///////////////////
+ /////////////////////////////////////////////////
+
+ private int getCaValidityDays() {
+ return 365 * caValidityYears;
+ }
+
+ private boolean saveNewRootCAKeypair() {
+ try {
+ LOG.debug("Generating root CA public/private keys");
+ final KeyPair keyPair = CertUtils.generateRandomKeyPair(2 * CAManager.CertKeySize.value());
+ if (!configDao.update(rootCAPublicKey.key(), rootCAPublicKey.category(), CertUtils.publicKeyToPem(keyPair.getPublic()))) {
+ LOG.error("Failed to save RootCA public key");
+ }
+ if (!configDao.update(rootCAPrivateKey.key(), rootCAPrivateKey.category(), CertUtils.privateKeyToPem(keyPair.getPrivate()))) {
+ LOG.error("Failed to save RootCA private key");
+ }
+ } catch (final NoSuchProviderException | NoSuchAlgorithmException | IOException e) {
+ LOG.error("Failed to generate/save RootCA private/public keys due to exception:", e);
+ }
+ return loadRootCAKeyPair();
+ }
+
+ private boolean saveNewRootCACertificate() {
+ if (caKeyPair == null) {
+ throw new CloudRuntimeException("Cannot issue self-signed root CA certificate as CA keypair is not initialized");
+ }
+ try {
+ LOG.debug("Generating root CA certificate");
+ final X509Certificate rootCaCertificate = CertUtils.generateV3Certificate(
+ null, caKeyPair, caKeyPair.getPublic(),
+ rootCAIssuerDN.value(), CAManager.CertSignatureAlgorithm.value(),
+ getCaValidityDays(), null, null);
+ if (!configDao.update(rootCACertificate.key(), rootCACertificate.category(), CertUtils.x509CertificateToPem(rootCaCertificate))) {
+ LOG.error("Failed to update RootCA public/x509 certificate");
+ }
+ } catch (final CertificateException | NoSuchAlgorithmException | NoSuchProviderException | SignatureException | InvalidKeyException | OperatorCreationException | IOException e) {
+ LOG.error("Failed to generate RootCA certificate from private/public keys due to exception:", e);
+ return false;
+ }
+ return loadRootCACertificate();
+ }
+
+ private boolean loadRootCAKeyPair() {
+ if (Strings.isNullOrEmpty(rootCAPublicKey.value()) || Strings.isNullOrEmpty(rootCAPrivateKey.value())) {
+ return false;
+ }
+ try {
+ caKeyPair = new KeyPair(CertUtils.pemToPublicKey(rootCAPublicKey.value()), CertUtils.pemToPrivateKey(rootCAPrivateKey.value()));
+ } catch (InvalidKeySpecException | IOException e) {
+ LOG.error("Failed to load saved RootCA private/public keys due to exception:", e);
+ return false;
+ }
+ return caKeyPair.getPrivate() != null && caKeyPair.getPublic() != null;
+ }
+
+ private boolean loadRootCACertificate() {
+ if (Strings.isNullOrEmpty(rootCACertificate.value())) {
+ return false;
+ }
+ try {
+ caCertificate = CertUtils.pemToX509Certificate(rootCACertificate.value());
+ caCertificate.verify(caKeyPair.getPublic());
+ } catch (final IOException | CertificateException | NoSuchAlgorithmException | InvalidKeyException | SignatureException | NoSuchProviderException e) {
+ LOG.error("Failed to load saved RootCA certificate due to exception:", e);
+ return false;
+ }
+ return caCertificate != null;
+ }
+
+ private boolean loadManagementKeyStore() {
+ if (managementKeyStore != null) {
+ return true;
+ }
+ final Certificate serverCertificate = issueCertificate(Collections.singletonList(NetUtils.getHostName()),
+ Collections.singletonList(NetUtils.getDefaultHostIp()), getCaValidityDays());
+ if (serverCertificate == null || serverCertificate.getPrivateKey() == null) {
+ throw new CloudRuntimeException("Failed to generate management server certificate and load management server keystore");
+ }
+ LOG.info("Creating new management server certificate and keystore");
+ try {
+ managementKeyStore = KeyStore.getInstance("JKS");
+ managementKeyStore.load(null, null);
+ managementKeyStore.setCertificateEntry(caAlias, caCertificate);
+ managementKeyStore.setKeyEntry(managementAlias, serverCertificate.getPrivateKey(), getKeyStorePassphrase(),
+ new X509Certificate[]{serverCertificate.getClientCertificate(), caCertificate});
+ } catch (final CertificateException | NoSuchAlgorithmException | KeyStoreException | IOException e) {
+ LOG.error("Failed to load root CA management-server keystore due to exception: ", e);
+ return false;
+ }
+ return managementKeyStore != null;
+ }
+
+ private boolean setupCA() {
+ if (!loadRootCAKeyPair() && !saveNewRootCAKeypair()) {
+ LOG.error("Failed to save and load root CA keypair");
+ return false;
+ }
+ if (!loadRootCACertificate() && !saveNewRootCACertificate()) {
+ LOG.error("Failed to save and load root CA certificate");
+ return false;
+ }
+ if (!loadManagementKeyStore()) {
+ LOG.error("Failed to check and configure management server keystore");
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean start() {
+ return loadRootCAKeyPair() && loadRootCAKeyPair() && loadManagementKeyStore();
+ }
+
+ @Override
+ public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+ super.configure(name, params);
+ Security.addProvider(new BouncyCastleProvider());
+ final GlobalLock caLock = GlobalLock.getInternLock("RootCAProviderSetup");
+ try {
+ if (caLock.lock(5 * 60)) {
+ try {
+ return setupCA();
+ } finally {
+ caLock.unlock();
+ }
+ } else {
+ LOG.error("Failed to grab lock and setup CA, startup method will try to load the CA certificate and keypair.");
+ }
+ } finally {
+ caLock.releaseRef();
+ }
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////
+ /////////////// Root CA Descriptors ///////////////////
+ ///////////////////////////////////////////////////////
+
+ @Override
+ public String getConfigComponentName() {
+ return RootCAProvider.class.getSimpleName();
+ }
+
+ @Override
+ public ConfigKey<?>[] getConfigKeys() {
+ return new ConfigKey<?>[]{
+ rootCAPrivateKey,
+ rootCAPublicKey,
+ rootCACertificate,
+ rootCAIssuerDN,
+ rootCAAuthStrictness,
+ rootCAAllowExpiredCert
+ };
+ }
+
+ @Override
+ public String getProviderName() {
+ return "root";
+ }
+
+ @Override
+ public String getDescription() {
+ return "CloudStack's Root CA provider plugin";
+ }
+}
diff --git a/plugins/ca/root-ca/test/org/apache/cloudstack/ca/provider/RootCACustomTrustManagerTest.java b/plugins/ca/root-ca/test/org/apache/cloudstack/ca/provider/RootCACustomTrustManagerTest.java
new file mode 100644
index 00000000000..8161d75e0ef
--- /dev/null
+++ b/plugins/ca/root-ca/test/org/apache/cloudstack/ca/provider/RootCACustomTrustManagerTest.java
@@ -0,0 +1,110 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.ca.provider;
+
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.cloudstack.utils.security.CertUtils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import com.cloud.certificate.CrlVO;
+import com.cloud.certificate.dao.CrlDao;
+
+@RunWith(MockitoJUnitRunner.class)
+public class RootCACustomTrustManagerTest {
+
+ @Mock
+ private CrlDao crlDao;
+ private KeyPair caKeypair;
+ private KeyPair clientKeypair;
+ private X509Certificate caCertificate;
+ private X509Certificate expiredClientCertificate;
+ private String clientIp = "1.2.3.4";
+ private Map<String, X509Certificate> certMap = new HashMap<>();
+
+ @Before
+ public void setUp() throws Exception {
+ certMap.clear();
+ caKeypair = CertUtils.generateRandomKeyPair(1024);
+ clientKeypair = CertUtils.generateRandomKeyPair(1024);
+ caCertificate = CertUtils.generateV3Certificate(null, caKeypair, caKeypair.getPublic(), "CN=ca", "SHA256withRSA", 365, null, null);
+ expiredClientCertificate = CertUtils.generateV3Certificate(caCertificate, caKeypair, clientKeypair.getPublic(),
+ "CN=cloudstack.apache.org", "SHA256withRSA", 0, Collections.singletonList("cloudstack.apache.org"), Collections.singletonList(clientIp));
+ }
+
+ @Test
+ public void testAuthNotStrict() throws Exception {
+ final RootCACustomTrustManager trustManager = new RootCACustomTrustManager(clientIp, false, true, certMap, caCertificate, crlDao);
+ trustManager.checkClientTrusted(null, null);
+ Assert.assertNull(trustManager.getAcceptedIssuers());
+ }
+
+ @Test(expected = CertificateException.class)
+ public void testAuthStrictWithInvalidCert() throws Exception {
+ final RootCACustomTrustManager trustManager = new RootCACustomTrustManager(clientIp, true, true, certMap, caCertificate, crlDao);
+ trustManager.checkClientTrusted(null, null);
+ }
+
+ @Test(expected = CertificateException.class)
+ public void testAuthStrictWithRevokedCert() throws Exception {
+ Mockito.when(crlDao.findBySerial(Mockito.any(BigInteger.class))).thenReturn(new CrlVO());
+ final RootCACustomTrustManager trustManager = new RootCACustomTrustManager(clientIp, true, true, certMap, caCertificate, crlDao);
+ trustManager.checkClientTrusted(new X509Certificate[]{caCertificate}, "RSA");
+ }
+
+ @Test(expected = CertificateException.class)
+ public void testAuthStrictWithInvalidCertOwnership() throws Exception {
+ Mockito.when(crlDao.findBySerial(Mockito.any(BigInteger.class))).thenReturn(null);
+ final RootCACustomTrustManager trustManager = new RootCACustomTrustManager(clientIp, true, true, certMap, caCertificate, crlDao);
+ trustManager.checkClientTrusted(new X509Certificate[]{caCertificate}, "RSA");
+ }
+
+ @Test(expected = CertificateException.class)
+ public void testAuthStrictWithDenyExpiredCertAndOwnership() throws Exception {
+ Mockito.when(crlDao.findBySerial(Mockito.any(BigInteger.class))).thenReturn(null);
+ final RootCACustomTrustManager trustManager = new RootCACustomTrustManager(clientIp, true, false, certMap, caCertificate, crlDao);
+ trustManager.checkClientTrusted(new X509Certificate[]{expiredClientCertificate}, "RSA");
+ }
+
+ @Test
+ public void testAuthStrictWithAllowExpiredCertAndOwnership() throws Exception {
+ Mockito.when(crlDao.findBySerial(Mockito.any(BigInteger.class))).thenReturn(null);
+ final RootCACustomTrustManager trustManager = new RootCACustomTrustManager(clientIp, true, true, certMap, caCertificate, crlDao);
+ Assert.assertTrue(trustManager.getAcceptedIssuers() != null);
+ Assert.assertTrue(trustManager.getAcceptedIssuers().length == 1);
+ Assert.assertEquals(trustManager.getAcceptedIssuers()[0], caCertificate);
+ trustManager.checkClientTrusted(new X509Certificate[]{expiredClientCertificate}, "RSA");
+ Assert.assertTrue(certMap.containsKey(clientIp));
+ Assert.assertEquals(certMap.get(clientIp), expiredClientCertificate);
+ }
+
+}
\ No newline at end of file
diff --git a/plugins/ca/root-ca/test/org/apache/cloudstack/ca/provider/RootCAProviderTest.java b/plugins/ca/root-ca/test/org/apache/cloudstack/ca/provider/RootCAProviderTest.java
new file mode 100644
index 00000000000..d5d64289da2
--- /dev/null
+++ b/plugins/ca/root-ca/test/org/apache/cloudstack/ca/provider/RootCAProviderTest.java
@@ -0,0 +1,155 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.ca.provider;
+
+import java.lang.reflect.Field;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SignatureException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+
+import javax.net.ssl.SSLEngine;
+
+import org.apache.cloudstack.framework.ca.Certificate;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.utils.security.CertUtils;
+import org.apache.cloudstack.utils.security.SSLUtils;
+import org.joda.time.DateTime;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class RootCAProviderTest {
+
+ private KeyPair caKeyPair;
+ private X509Certificate caCertificate;
+
+ private RootCAProvider provider;
+
+ private void addField(final RootCAProvider provider, final String name, final Object o) throws IllegalAccessException, NoSuchFieldException {
+ Field f = RootCAProvider.class.getDeclaredField(name);
+ f.setAccessible(true);
+ f.set(provider, o);
+ }
+
+ private void overrideDefaultConfigValue(final ConfigKey configKey, final String name, final Object o) throws IllegalAccessException, NoSuchFieldException {
+ Field f = ConfigKey.class.getDeclaredField(name);
+ f.setAccessible(true);
+ f.set(configKey, o);
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ caKeyPair = CertUtils.generateRandomKeyPair(1024);
+ caCertificate = CertUtils.generateV3Certificate(null, caKeyPair, caKeyPair.getPublic(), "CN=ca", "SHA256withRSA", 365, null, null);
+
+ provider = new RootCAProvider();
+
+ addField(provider, "caKeyPair", caKeyPair);
+ addField(provider, "caCertificate", caCertificate);
+ addField(provider, "caKeyPair", caKeyPair);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ @Test
+ public void testCanProvisionCertificates() {
+ Assert.assertTrue(provider.canProvisionCertificates());
+ }
+
+ @Test
+ public void testGetCaCertificate() {
+ Assert.assertTrue(provider.getCaCertificate().size() == 1);
+ Assert.assertEquals(provider.getCaCertificate().get(0), caCertificate);
+ }
+
+ @Test
+ public void testIssueCertificateWithoutCsr() throws NoSuchProviderException, CertificateException, NoSuchAlgorithmException, InvalidKeyException, SignatureException {
+ final Certificate certificate = provider.issueCertificate(Arrays.asList("domain1.com", "domain2.com"), null, 1);
+ Assert.assertTrue(certificate != null);
+ Assert.assertTrue(certificate.getPrivateKey() != null);
+ Assert.assertEquals(certificate.getCaCertificates().get(0), caCertificate);
+ Assert.assertEquals(certificate.getClientCertificate().getIssuerDN(), caCertificate.getIssuerDN());
+ Assert.assertTrue(certificate.getClientCertificate().getNotAfter().before(new DateTime().plusDays(1).toDate()));
+ certificate.getClientCertificate().verify(caCertificate.getPublicKey());
+ }
+
+ @Test
+ public void testIssueCertificateWithCsr() throws NoSuchProviderException, CertificateException, NoSuchAlgorithmException, InvalidKeyException, SignatureException {
+ final String csr = "-----BEGIN NEW CERTIFICATE REQUEST-----\n" +
+ "MIICxTCCAa0CAQAwUDETMBEGA1UEBhMKY2xvdWRzdGFjazETMBEGA1UEChMKY2xvdWRzdGFjazET\n" +
+ "MBEGA1UECxMKY2xvdWRzdGFjazEPMA0GA1UEAxMGdi0xLVZNMIIBIjANBgkqhkiG9w0BAQEFAAOC\n" +
+ "AQ8AMIIBCgKCAQEAhi3hOrt/p0hUmoW2A+2gFAMxSINItRrHfQ6VUnHhYKZGcTN9honVFuu30tz7\n" +
+ "oSLUUx1laWEWLlIozpUcPSjOuPa5a0JS8kjplMd8DLfLNeQ6gcuEWznMRJqCaKM72qn/FAK3r11l\n" +
+ "2NofEfWbHU5QVQ5CsYF0JndspLcnmf0tnmreAzz6vlSEPQd4g2hTSsPb72eAqYd0eJnl2oXe7cF3\n" +
+ "iemg6/lWoxlh8njVFDKJ5ibNQA/RSc5syzzaQ8fn/AkZlChR5pml47elfC3GuqetfZPAEP4rebXV\n" +
+ "zEw+UVbMo5bWx4AYm1S2HxhmsWC/1J5oxluZDtC6tjMqnkKQze8HbQIDAQABoDAwLgYJKoZIhvcN\n" +
+ "AQkOMSEwHzAdBgNVHQ4EFgQUdgA1C/7vW3lUcb/dnolGjZB55/AwDQYJKoZIhvcNAQELBQADggEB\n" +
+ "AH6ynWbyW5o4h2yEvmcr+upmu/LZYkpfwIWIo+dfrHX9OHu0rhHDIgMgqEStWzrOfhAkcEocQo21\n" +
+ "E4Q39nECO+cgTCQ1nfH5BVqaMEg++n6tqXBwLmAQJkftEmB+YUPFB9OGn5TQY9Pcnof95Y8xnvtR\n" +
+ "0DvVQa9RM9IsqxgvU4wQCcaNHuEC46Wzo7lyYJ6p//GLw8UQnHxsWktt8U+vyaqXjOvz0+nJobUz\n" +
+ "Jv7r7DFkOwgS6ObBczaZsv1yx2YklcKfbsI7xVsvZAXFey2RsvSJi1QPEJC5XbwDenWnCSrPfjJg\n" +
+ "SLJ0p9tV70D6v07r1OOmBtvU5AH4N+vioAZA0BE=\n" +
+ "-----END NEW CERTIFICATE REQUEST-----\n";
+ final Certificate certificate = provider.issueCertificate(csr, Arrays.asList("v-1-VM", "domain1.com", "domain2.com"), null, 1);
+ Assert.assertTrue(certificate != null);
+ Assert.assertTrue(certificate.getPrivateKey() == null);
+ Assert.assertEquals(certificate.getCaCertificates().get(0), caCertificate);
+ Assert.assertTrue(certificate.getClientCertificate().getSubjectDN().toString().startsWith("CN=v-1-VM,"));
+ certificate.getClientCertificate().verify(caCertificate.getPublicKey());
+ }
+
+ @Test
+ public void testRevokeCertificate() throws Exception {
+ Assert.assertTrue(provider.revokeCertificate(CertUtils.generateRandomBigInt(), "anyString"));
+ }
+
+ @Test
+ public void testCreateSSLEngineWithoutAuthStrictness() throws Exception {
+ overrideDefaultConfigValue(RootCAProvider.rootCAAuthStrictness, "_defaultValue", "false");
+ final SSLEngine e = provider.createSSLEngine(SSLUtils.getSSLContext(), "/1.2.3.4:5678", null);
+ Assert.assertFalse(e.getUseClientMode());
+ Assert.assertFalse(e.getNeedClientAuth());
+ }
+
+ @Test
+ public void testCreateSSLEngineWithAuthStrictness() throws Exception {
+ overrideDefaultConfigValue(RootCAProvider.rootCAAuthStrictness, "_defaultValue", "true");
+ final SSLEngine e = provider.createSSLEngine(SSLUtils.getSSLContext(), "/1.2.3.4:5678", null);
+ Assert.assertFalse(e.getUseClientMode());
+ Assert.assertTrue(e.getNeedClientAuth());
+ }
+
+ @Test
+ public void testGetProviderName() throws Exception {
+ Assert.assertEquals(provider.getProviderName(), "root");
+ }
+
+}
\ No newline at end of file
diff --git a/plugins/database/mysql-ha/pom.xml b/plugins/database/mysql-ha/pom.xml
index fdfb52bbecc..9db88c77187 100644
--- a/plugins/database/mysql-ha/pom.xml
+++ b/plugins/database/mysql-ha/pom.xml
@@ -15,7 +15,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/database/quota/pom.xml b/plugins/database/quota/pom.xml
index 585cda20274..031b5de3284 100644
--- a/plugins/database/quota/pom.xml
+++ b/plugins/database/quota/pom.xml
@@ -16,7 +16,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/dedicated-resources/pom.xml b/plugins/dedicated-resources/pom.xml
index 097e2df65d0..507f3972d0b 100644
--- a/plugins/dedicated-resources/pom.xml
+++ b/plugins/dedicated-resources/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
</project>
diff --git a/plugins/deployment-planners/implicit-dedication/pom.xml b/plugins/deployment-planners/implicit-dedication/pom.xml
index 1b7afe43e2e..f6ccc4c2dfa 100644
--- a/plugins/deployment-planners/implicit-dedication/pom.xml
+++ b/plugins/deployment-planners/implicit-dedication/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
</project>
diff --git a/plugins/deployment-planners/user-concentrated-pod/pom.xml b/plugins/deployment-planners/user-concentrated-pod/pom.xml
index 45e549d5f46..b9628dd44cb 100644
--- a/plugins/deployment-planners/user-concentrated-pod/pom.xml
+++ b/plugins/deployment-planners/user-concentrated-pod/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
</project>
diff --git a/plugins/deployment-planners/user-dispersing/pom.xml b/plugins/deployment-planners/user-dispersing/pom.xml
index 789c29db767..b9e3f3781aa 100644
--- a/plugins/deployment-planners/user-dispersing/pom.xml
+++ b/plugins/deployment-planners/user-dispersing/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
</project>
diff --git a/plugins/event-bus/inmemory/pom.xml b/plugins/event-bus/inmemory/pom.xml
index 52f330ec400..fdf72f80343 100644
--- a/plugins/event-bus/inmemory/pom.xml
+++ b/plugins/event-bus/inmemory/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/event-bus/kafka/pom.xml b/plugins/event-bus/kafka/pom.xml
index f273bfa8503..e39596146f3 100644
--- a/plugins/event-bus/kafka/pom.xml
+++ b/plugins/event-bus/kafka/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
@@ -36,7 +36,7 @@
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
- <version>0.10.1.1</version>
+ <version>0.11.0.1</version>
</dependency>
</dependencies>
<build>
diff --git a/plugins/event-bus/rabbitmq/pom.xml b/plugins/event-bus/rabbitmq/pom.xml
index 6179582f1f3..50c7710fce6 100644
--- a/plugins/event-bus/rabbitmq/pom.xml
+++ b/plugins/event-bus/rabbitmq/pom.xml
@@ -24,14 +24,14 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
- <version>3.6.6</version>
+ <version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
diff --git a/plugins/file-systems/netapp/pom.xml b/plugins/file-systems/netapp/pom.xml
index 3251dea8ea0..a330a89e07f 100644
--- a/plugins/file-systems/netapp/pom.xml
+++ b/plugins/file-systems/netapp/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/ha-planners/skip-heurestics/pom.xml b/plugins/ha-planners/skip-heurestics/pom.xml
index dfddfb2a89b..d0bea854c76 100644
--- a/plugins/ha-planners/skip-heurestics/pom.xml
+++ b/plugins/ha-planners/skip-heurestics/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
</project>
diff --git a/plugins/host-allocators/random/pom.xml b/plugins/host-allocators/random/pom.xml
index 4fd225e67b1..3f4b35b874b 100644
--- a/plugins/host-allocators/random/pom.xml
+++ b/plugins/host-allocators/random/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
</project>
diff --git a/plugins/hypervisors/baremetal/pom.xml b/plugins/hypervisors/baremetal/pom.xml
index 49988c713ee..82d3e3ba7c5 100755
--- a/plugins/hypervisors/baremetal/pom.xml
+++ b/plugins/hypervisors/baremetal/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>cloud-plugin-hypervisor-baremetal</artifactId>
diff --git a/plugins/hypervisors/hyperv/pom.xml b/plugins/hypervisors/hyperv/pom.xml
index f4652834860..840f43a505d 100644
--- a/plugins/hypervisors/hyperv/pom.xml
+++ b/plugins/hypervisors/hyperv/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<properties>
diff --git a/plugins/hypervisors/kvm/pom.xml b/plugins/hypervisors/kvm/pom.xml
index b4bb3711e05..4905b028520 100644
--- a/plugins/hypervisors/kvm/pom.xml
+++ b/plugins/hypervisors/kvm/pom.xml
@@ -15,7 +15,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/hypervisors/kvm/resources/META-INF/cloudstack/kvm-compute/spring-kvm-compute-context.xml b/plugins/hypervisors/kvm/resources/META-INF/cloudstack/kvm-compute/spring-kvm-compute-context.xml
index 3c51a233275..9bcfdd9c306 100644
--- a/plugins/hypervisors/kvm/resources/META-INF/cloudstack/kvm-compute/spring-kvm-compute-context.xml
+++ b/plugins/hypervisors/kvm/resources/META-INF/cloudstack/kvm-compute/spring-kvm-compute-context.xml
@@ -30,5 +30,12 @@
<bean id="KVMInvestigator" class="com.cloud.ha.KVMInvestigator">
<property name="name" value="KVMInvestigator" />
</bean>
+
+ <bean id="KVMHostActivityChecker" class="org.apache.cloudstack.kvm.ha.KVMHostActivityChecker">
+ </bean>
+
+ <bean id="KVMHAProvider" class="org.apache.cloudstack.kvm.ha.KVMHAProvider">
+ <property name="name" value="KVMHAProvider" />
+ </bean>
</beans>
diff --git a/plugins/hypervisors/kvm/src/com/cloud/ha/KVMInvestigator.java b/plugins/hypervisors/kvm/src/com/cloud/ha/KVMInvestigator.java
index 8337a7b7646..a6cddc7dfab 100644
--- a/plugins/hypervisors/kvm/src/com/cloud/ha/KVMInvestigator.java
+++ b/plugins/hypervisors/kvm/src/com/cloud/ha/KVMInvestigator.java
@@ -29,7 +29,7 @@
import com.cloud.resource.ResourceManager;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.utils.component.AdapterBase;
-
+import org.apache.cloudstack.ha.HAManager;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.log4j.Logger;
@@ -40,17 +40,23 @@
public class KVMInvestigator extends AdapterBase implements Investigator {
private final static Logger s_logger = Logger.getLogger(KVMInvestigator.class);
@Inject
- HostDao _hostDao;
+ private HostDao _hostDao;
+ @Inject
+ private AgentManager _agentMgr;
@Inject
- AgentManager _agentMgr;
+ private ResourceManager _resourceMgr;
@Inject
- ResourceManager _resourceMgr;
+ private PrimaryDataStoreDao _storagePoolDao;
@Inject
- PrimaryDataStoreDao _storagePoolDao;
+ private HAManager haManager;
@Override
public boolean isVmAlive(com.cloud.vm.VirtualMachine vm, Host host) throws UnknownVM {
+ if (haManager.isHAEligible(host)) {
+ return haManager.isVMAliveOnHost(host);
+ }
Status status = isAgentAlive(host);
+ s_logger.debug("HA: HOST is ineligible legacy state " + status + " for host " + host.getId());
if (status == null) {
throw new UnknownVM();
}
@@ -67,6 +73,10 @@ public Status isAgentAlive(Host agent) {
return null;
}
+ if (haManager.isHAEligible(agent)) {
+ return haManager.getHostStatus(agent);
+ }
+
List<StoragePoolVO> clusterPools = _storagePoolDao.listPoolsByCluster(agent.getClusterId());
boolean hasNfs = false;
for (StoragePoolVO pool : clusterPools) {
@@ -123,6 +133,7 @@ public Status isAgentAlive(Host agent) {
if (neighbourStatus == Status.Down && (hostStatus == Status.Disconnected || hostStatus == Status.Down)) {
hostStatus = Status.Down;
}
+ s_logger.debug("HA: HOST is ineligible legacy state " + hostStatus + " for host " + agent.getId());
return hostStatus;
}
}
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHABase.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHABase.java
index b829f78f625..be5ab396d19 100644
--- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHABase.java
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHABase.java
@@ -179,4 +179,9 @@ protected String runScriptRetry(String cmdString, OutputInterpreter interpreter)
return result;
}
+
+ public Boolean checkingHB() {
+ // TODO Auto-generated method stub
+ return null;
+ }
}
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAChecker.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAChecker.java
index 565673ec7bc..3905b1ede30 100644
--- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAChecker.java
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAChecker.java
@@ -40,10 +40,10 @@ public KVMHAChecker(List<NfsStoragePool> pools, String host) {
* True means heartbeaing is on going, or we can't get it's status. False
* means heartbeating is stopped definitely
*/
- private Boolean checkingHB() {
+ @Override
+ public Boolean checkingHB() {
List<Boolean> results = new ArrayList<Boolean>();
for (NfsStoragePool pool : _pools) {
-
Script cmd = new Script(s_heartBeatPath, _heartBeatCheckerTimeout, s_logger);
cmd.add("-i", pool._poolIp);
cmd.add("-p", pool._poolMountSourcePath);
@@ -53,9 +53,9 @@ private Boolean checkingHB() {
cmd.add("-t", String.valueOf(_heartBeatUpdateFreq / 1000));
OutputInterpreter.OneLineParser parser = new OutputInterpreter.OneLineParser();
String result = cmd.execute(parser);
- s_logger.debug("pool: " + pool._poolIp);
- s_logger.debug("reture: " + result);
- s_logger.debug("parser: " + parser.getLine());
+ s_logger.debug("KVMHAChecker pool: " + pool._poolIp);
+ s_logger.debug("KVMHAChecker result: " + result);
+ s_logger.debug("KVMHAChecker parser: " + parser.getLine());
if (result == null && parser.getLine().contains("> DEAD <")) {
s_logger.debug("read heartbeat failed: ");
results.add(false);
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAMonitor.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAMonitor.java
index 49aa99cea68..0cebb4c9b00 100644
--- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAMonitor.java
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAMonitor.java
@@ -16,22 +16,20 @@
// under the License.
package com.cloud.hypervisor.kvm.resource;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
+import com.cloud.utils.script.Script;
+import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.log4j.Logger;
import org.libvirt.Connect;
import org.libvirt.LibvirtException;
import org.libvirt.StoragePool;
import org.libvirt.StoragePoolInfo.StoragePoolState;
-import org.apache.cloudstack.managed.context.ManagedContextRunnable;
-
-import com.cloud.utils.script.Script;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
public class KVMHAMonitor extends KVMHABase implements Runnable {
private static final Logger s_logger = Logger.getLogger(KVMHAMonitor.class);
@@ -73,6 +71,12 @@ public void removeStoragePool(String uuid) {
}
}
+ public NfsStoragePool getStoragePool(String uuid) {
+ synchronized (_storagePool) {
+ return _storagePool.get(uuid);
+ }
+ }
+
private class Monitor extends ManagedContextRunnable {
@Override
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAVMActivityChecker.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAVMActivityChecker.java
new file mode 100644
index 00000000000..f14d0a25b7f
--- /dev/null
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAVMActivityChecker.java
@@ -0,0 +1,70 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.hypervisor.kvm.resource;
+
+import com.cloud.utils.script.OutputInterpreter;
+import com.cloud.utils.script.Script;
+import org.apache.log4j.Logger;
+import org.joda.time.Duration;
+
+import java.util.concurrent.Callable;
+
+public class KVMHAVMActivityChecker extends KVMHABase implements Callable<Boolean> {
+ private static final Logger LOG = Logger.getLogger(KVMHAVMActivityChecker.class);
+
+ final private NfsStoragePool nfsStoragePool;
+ final private String hostIP;
+ final private String volumeUuidList;
+ final private String vmActivityCheckPath;
+ final private Duration activityScriptTimeout = Duration.standardSeconds(3600L);
+ final private long suspectTimeInSeconds;
+
+ public KVMHAVMActivityChecker(final NfsStoragePool pool, final String host, final String volumeUUIDListString, String vmActivityCheckPath, final long suspectTime) {
+ this.nfsStoragePool = pool;
+ this.hostIP = host;
+ this.volumeUuidList = volumeUUIDListString;
+ this.vmActivityCheckPath = vmActivityCheckPath;
+ this.suspectTimeInSeconds = suspectTime;
+ }
+
+ @Override
+ public Boolean checkingHB() {
+ Script cmd = new Script(vmActivityCheckPath, activityScriptTimeout.getStandardSeconds(), LOG);
+ cmd.add("-i", nfsStoragePool._poolIp);
+ cmd.add("-p", nfsStoragePool._poolMountSourcePath);
+ cmd.add("-m", nfsStoragePool._mountDestPath);
+ cmd.add("-h", hostIP);
+ cmd.add("-u", volumeUuidList);
+ cmd.add("-t", String.valueOf(String.valueOf(System.currentTimeMillis() / 1000)));
+ cmd.add("-d", String.valueOf(suspectTimeInSeconds));
+ OutputInterpreter.OneLineParser parser = new OutputInterpreter.OneLineParser();
+ String result = cmd.execute(parser);
+ LOG.debug("KVMHAVMActivityChecker pool: " + nfsStoragePool._poolIp);
+ LOG.debug("KVMHAVMActivityChecker result: " + result);
+ LOG.debug("KVMHAVMActivityChecker parser: " + parser.getLine());
+ if (result == null && parser.getLine().contains("DEAD")) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ @Override
+ public Boolean call() throws Exception {
+ return checkingHB();
+ }
+}
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
index 58db46609cf..77942499a93 100644
--- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
@@ -89,6 +89,7 @@
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.agent.api.StartupStorageCommand;
import com.cloud.agent.api.VmDiskStatsEntry;
+import com.cloud.agent.api.VmNetworkStatsEntry;
import com.cloud.agent.api.VmStatsEntry;
import com.cloud.agent.api.routing.IpAssocCommand;
import com.cloud.agent.api.routing.IpAssocVpcCommand;
@@ -132,6 +133,9 @@
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.VideoDef;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.RngDef;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.RngDef.RngBackendModel;
+import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.WatchDogDef;
+import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.WatchDogDef.WatchDogModel;
+import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.WatchDogDef.WatchDogAction;
import com.cloud.hypervisor.kvm.resource.wrapper.LibvirtRequestWrapper;
import com.cloud.hypervisor.kvm.resource.wrapper.LibvirtUtilitiesHelper;
import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk;
@@ -200,6 +204,7 @@
private String _resizeVolumePath;
private String _createTmplPath;
private String _heartBeatPath;
+ private String _vmActivityCheckPath;
private String _securityGroupPath;
private String _ovsPvlanDhcpHostPath;
private String _ovsPvlanVmPath;
@@ -272,6 +277,8 @@
private File _qemuSocketsPath;
private final String _qemuGuestAgentSocketName = "org.qemu.guest_agent.0";
private long _totalMemory;
+ protected WatchDogAction _watchDogAction = WatchDogAction.NONE;
+ protected WatchDogModel _watchDogModel = WatchDogModel.I6300ESB;
private final Map <String, String> _pifs = new HashMap<String, String>();
private final Map<String, VmStats> _vmStats = new ConcurrentHashMap<String, VmStats>();
@@ -297,6 +304,8 @@
private long _dom0MinMem;
+ private long _dom0OvercommitMem;
+
protected boolean _disconnected = true;
protected int _cmdsTimeout;
protected int _stopTimeout;
@@ -446,6 +455,10 @@ public String getGuestBridgeName() {
return _guestBridgeName;
}
+ public String getVmActivityCheckPath() {
+ return _vmActivityCheckPath;
+ }
+
public String getOvsPvlanDhcpHostPath() {
return _ovsPvlanDhcpHostPath;
}
@@ -686,6 +699,11 @@ public boolean configure(final String name, final Map<String, Object> params) th
throw new ConfigurationException("Unable to find the resizevolume.sh");
}
+ _vmActivityCheckPath = Script.findScript(kvmScriptsDir, "kvmvmactivity.sh");
+ if (_vmActivityCheckPath == null) {
+ throw new ConfigurationException("Unable to find kvmvmactivity.sh");
+ }
+
_createTmplPath = Script.findScript(storageScriptsDir, "createtmplt.sh");
if (_createTmplPath == null) {
throw new ConfigurationException("Unable to find the createtmplt.sh");
@@ -833,6 +851,11 @@ public boolean configure(final String name, final Map<String, Object> params) th
// Reserve 1GB unless admin overrides
_dom0MinMem = NumbersUtil.parseInt(value, 1024) * 1024 * 1024L;
+ value = (String)params.get("host.overcommit.mem.mb");
+ // Support overcommit memory for host if host uses ZSWAP, KSM and other memory
+ // compressing technologies
+ _dom0OvercommitMem = NumbersUtil.parseInt(value, 0) * 1024 * 1024L;
+
value = (String) params.get("kvmclock.disable");
if (Boolean.parseBoolean(value)) {
_noKvmClock = true;
@@ -859,6 +882,16 @@ public boolean configure(final String name, final Map<String, Object> params) th
_rngRatePeriod = NumbersUtil.parseInt(value, new Integer(_rngRatePeriod));
}
+ value = (String) params.get("vm.watchdog.model");
+ if (!Strings.isNullOrEmpty(value)) {
+ _watchDogModel = WatchDogModel.valueOf(value.toUpperCase());
+ }
+
+ value = (String) params.get("vm.watchdog.action");
+ if (!Strings.isNullOrEmpty(value)) {
+ _watchDogAction = WatchDogAction.valueOf(value.toUpperCase());
+ }
+
LibvirtConnection.initialize(_hypervisorURI);
Connect conn = null;
try {
@@ -2055,6 +2088,8 @@ So if getMinSpeed() returns null we fall back to getSpeed().
devices.addDevice(new ChannelDef(_qemuGuestAgentSocketName, ChannelDef.ChannelType.UNIX,
new File(_qemuSocketsPath + "/" + vmTO.getName() + "." + _qemuGuestAgentSocketName)));
+ devices.addDevice(new WatchDogDef(_watchDogAction, _watchDogModel));
+
final VideoDef videoCard = new VideoDef(_videoHw, _videoRam);
devices.addDevice(videoCard);
@@ -2754,12 +2789,12 @@ private String getIqn() {
info.add((int)cpus);
info.add(speed);
// Report system's RAM as actual RAM minus host OS reserved RAM
- ram = ram - _dom0MinMem;
+ ram = ram - _dom0MinMem + _dom0OvercommitMem;
info.add(ram);
info.add(cap);
info.add(_dom0MinMem);
info.add(cpuSockets);
- s_logger.debug("cpus=" + cpus + ", speed=" + speed + ", ram=" + ram + ", _dom0MinMem=" + _dom0MinMem + ", cpu sockets=" + cpuSockets);
+ s_logger.debug("cpus=" + cpus + ", speed=" + speed + ", ram=" + ram + ", _dom0MinMem=" + _dom0MinMem + ", _dom0OvercommitMem=" + _dom0OvercommitMem + ", cpu sockets=" + cpuSockets);
return info;
}
@@ -3114,6 +3149,30 @@ private String executeBashScript(final String script) {
return command.execute();
}
+ public List<VmNetworkStatsEntry> getVmNetworkStat(Connect conn, String vmName) throws LibvirtException {
+ Domain dm = null;
+ try {
+ dm = getDomain(conn, vmName);
+
+ List<VmNetworkStatsEntry> stats = new ArrayList<VmNetworkStatsEntry>();
+
+ List<InterfaceDef> nics = getInterfaces(conn, vmName);
+
+ for (InterfaceDef nic : nics) {
+ DomainInterfaceStats nicStats = dm.interfaceStats(nic.getDevName());
+ String macAddress = nic.getMacAddress();
+ VmNetworkStatsEntry stat = new VmNetworkStatsEntry(vmName, macAddress, nicStats.tx_bytes, nicStats.rx_bytes);
+ stats.add(stat);
+ }
+
+ return stats;
+ } finally {
+ if (dm != null) {
+ dm.free();
+ }
+ }
+ }
+
public List<VmDiskStatsEntry> getVmDiskStat(final Connect conn, final String vmName) throws LibvirtException {
Domain dm = null;
try {
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtDomainXMLParser.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtDomainXMLParser.java
index 3c4dc11ec9c..847d77553f4 100644
--- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtDomainXMLParser.java
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtDomainXMLParser.java
@@ -43,6 +43,9 @@
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef.NicModel;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.RngDef;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.RngDef.RngBackendModel;
+import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.WatchDogDef;
+import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.WatchDogDef.WatchDogModel;
+import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.WatchDogDef.WatchDogAction;
public class LibvirtDomainXMLParser {
private static final Logger s_logger = Logger.getLogger(LibvirtDomainXMLParser.class);
@@ -50,6 +53,7 @@
private final List<DiskDef> diskDefs = new ArrayList<DiskDef>();
private final List<RngDef> rngDefs = new ArrayList<RngDef>();
private final List<ChannelDef> channels = new ArrayList<ChannelDef>();
+ private final List<WatchDogDef> watchDogDefs = new ArrayList<WatchDogDef>();
private Integer vncPort;
private String desc;
@@ -237,6 +241,27 @@ public boolean parseDomainXML(String domXML) {
rngDefs.add(def);
}
+ NodeList watchDogs = devices.getElementsByTagName("watchdog");
+ for (int i = 0; i < watchDogs.getLength(); i++) {
+ WatchDogDef def = null;
+ Element watchDog = (Element)watchDogs.item(i);
+ String action = watchDog.getAttribute("action");
+ String model = watchDog.getAttribute("model");
+
+ if (Strings.isNullOrEmpty(model)) {
+ continue;
+ }
+
+ if (Strings.isNullOrEmpty(action)) {
+ def = new WatchDogDef(WatchDogModel.valueOf(model.toUpperCase()));
+ } else {
+ def = new WatchDogDef(WatchDogAction.valueOf(action.toUpperCase()),
+ WatchDogModel.valueOf(model.toUpperCase()));
+ }
+
+ watchDogDefs.add(def);
+ }
+
return true;
} catch (ParserConfigurationException e) {
s_logger.debug(e.toString());
@@ -290,6 +315,10 @@ public Integer getVncPort() {
return Collections.unmodifiableList(channels);
}
+ public List<WatchDogDef> getWatchDogs() {
+ return watchDogDefs;
+ }
+
public String getDescription() {
return desc;
}
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java
index ffc93de41e7..ff3eb03ebdf 100644
--- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java
@@ -1612,6 +1612,67 @@ public String toString() {
}
}
+ public static class WatchDogDef {
+ enum WatchDogModel {
+ I6300ESB("i6300esb"), IB700("ib700"), DIAG288("diag288");
+ String model;
+
+ WatchDogModel(String model) {
+ this.model = model;
+ }
+
+ @Override
+ public String toString() {
+ return model;
+ }
+ }
+
+ enum WatchDogAction {
+ RESET("reset"), SHUTDOWN("shutdown"), POWEROFF("poweroff"), PAUSE("pause"), NONE("none"), DUMP("dump");
+ String action;
+
+ WatchDogAction(String action) {
+ this.action = action;
+ }
+
+ @Override
+ public String toString() {
+ return action;
+ }
+ }
+
+ WatchDogModel model = WatchDogModel.I6300ESB;
+ WatchDogAction action = WatchDogAction.NONE;
+
+ public WatchDogDef(WatchDogAction action) {
+ this.action = action;
+ }
+
+ public WatchDogDef(WatchDogModel model) {
+ this.model = model;
+ }
+
+ public WatchDogDef(WatchDogAction action, WatchDogModel model) {
+ this.action = action;
+ this.model = model;
+ }
+
+ public WatchDogAction getAction() {
+ return action;
+ }
+
+ public WatchDogModel getModel() {
+ return model;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder wacthDogBuilder = new StringBuilder();
+ wacthDogBuilder.append("<watchdog model='" + model + "' action='" + action + "'/>\n");
+ return wacthDogBuilder.toString();
+ }
+ }
+
public void setHvsType(String hvs) {
_hvsType = hvs;
}
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckOnHostCommandWrapper.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckOnHostCommandWrapper.java
index bc648f2f446..651cdc9e888 100644
--- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckOnHostCommandWrapper.java
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckOnHostCommandWrapper.java
@@ -53,14 +53,14 @@ public Answer execute(final CheckOnHostCommand command, final LibvirtComputingRe
try {
final Boolean result = future.get();
if (result) {
- return new Answer(command, false, "Heart is still beating...");
+ return new Answer(command, false, "Heart is beating...");
} else {
return new Answer(command);
}
} catch (final InterruptedException e) {
- return new Answer(command, false, "can't get status of host:");
+ return new Answer(command, false, "CheckOnHostCommand: can't get status of host: InterruptedException");
} catch (final ExecutionException e) {
- return new Answer(command, false, "can't get status of host:");
+ return new Answer(command, false, "CheckOnHostCommand: can't get status of host: ExecutionException");
}
}
}
\ No newline at end of file
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckVMActivityOnStoragePoolCommandWrapper.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckVMActivityOnStoragePoolCommandWrapper.java
new file mode 100644
index 00000000000..9c899a04055
--- /dev/null
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckVMActivityOnStoragePoolCommandWrapper.java
@@ -0,0 +1,65 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package com.cloud.hypervisor.kvm.resource.wrapper;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.CheckVMActivityOnStoragePoolCommand;
+import com.cloud.agent.api.to.StorageFilerTO;
+import com.cloud.hypervisor.kvm.resource.KVMHABase.NfsStoragePool;
+import com.cloud.hypervisor.kvm.resource.KVMHAMonitor;
+import com.cloud.hypervisor.kvm.resource.KVMHAVMActivityChecker;
+import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
+import com.cloud.resource.CommandWrapper;
+import com.cloud.resource.ResourceWrapper;
+import com.cloud.storage.Storage;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+@ResourceWrapper(handles = CheckVMActivityOnStoragePoolCommand.class)
+public final class LibvirtCheckVMActivityOnStoragePoolCommandWrapper extends CommandWrapper<CheckVMActivityOnStoragePoolCommand, Answer, LibvirtComputingResource> {
+
+ @Override
+ public Answer execute(final CheckVMActivityOnStoragePoolCommand command, final LibvirtComputingResource libvirtComputingResource) {
+ final ExecutorService executors = Executors.newSingleThreadExecutor();
+ final KVMHAMonitor monitor = libvirtComputingResource.getMonitor();
+ final StorageFilerTO pool = command.getPool();
+ if (Storage.StoragePoolType.NetworkFilesystem == pool.getType()){
+ final NfsStoragePool nfspool = monitor.getStoragePool(pool.getUuid());
+ final KVMHAVMActivityChecker ha = new KVMHAVMActivityChecker(nfspool, command.getHost().getPrivateNetwork().getIp(), command.getVolumeList(), libvirtComputingResource.getVmActivityCheckPath(), command.getSuspectTimeInSeconds());
+ final Future<Boolean> future = executors.submit(ha);
+ try {
+ final Boolean result = future.get();
+ if (result) {
+ return new Answer(command, false, "VMHA disk activity detected ...");
+ } else {
+ return new Answer(command);
+ }
+ } catch (InterruptedException e) {
+ return new Answer(command, false, "CheckVMActivityOnStoragePoolCommand: can't get status of host: InterruptedException");
+ } catch (ExecutionException e) {
+ return new Answer(command, false, "CheckVMActivityOnStoragePoolCommand: can't get status of host: ExecutionException");
+ }
+ }
+ return new Answer(command, false, "Unsupported Storage");
+ }
+}
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetVmNetworkStatsCommandWrapper.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetVmNetworkStatsCommandWrapper.java
new file mode 100644
index 00000000000..20ee4fd9dea
--- /dev/null
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetVmNetworkStatsCommandWrapper.java
@@ -0,0 +1,68 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package com.cloud.hypervisor.kvm.resource.wrapper;
+
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.libvirt.Connect;
+import org.libvirt.LibvirtException;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.GetVmNetworkStatsAnswer;
+import com.cloud.agent.api.GetVmNetworkStatsCommand;
+import com.cloud.agent.api.VmNetworkStatsEntry;
+import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
+import com.cloud.resource.CommandWrapper;
+import com.cloud.resource.ResourceWrapper;
+
+@ResourceWrapper(handles = GetVmNetworkStatsCommand.class)
+public final class LibvirtGetVmNetworkStatsCommandWrapper extends CommandWrapper<GetVmNetworkStatsCommand, Answer, LibvirtComputingResource> {
+
+ private static final Logger s_logger = Logger.getLogger(LibvirtGetVmNetworkStatsCommandWrapper.class);
+
+ @Override
+ public Answer execute(final GetVmNetworkStatsCommand command, final LibvirtComputingResource libvirtComputingResource) {
+ final List<String> vmNames = command.getVmNames();
+ final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
+
+ try {
+ final HashMap<String, List<VmNetworkStatsEntry>> vmNetworkStatsNameMap = new HashMap<String, List<VmNetworkStatsEntry>>();
+ final Connect conn = libvirtUtilitiesHelper.getConnection();
+ for (final String vmName : vmNames) {
+ try {
+ final List<VmNetworkStatsEntry> statEntry = libvirtComputingResource.getVmNetworkStat(conn, vmName);
+ if (statEntry == null) {
+ continue;
+ }
+
+ vmNetworkStatsNameMap.put(vmName, statEntry);
+ } catch (LibvirtException e) {
+ s_logger.warn("Can't get vm network stats: " + e.toString() + ", continue");
+ }
+ }
+ return new GetVmNetworkStatsAnswer(command, "", command.getHostName(), vmNetworkStatsNameMap);
+ } catch (final LibvirtException e) {
+ s_logger.debug("Can't get vm network stats: " + e.toString());
+ return new GetVmNetworkStatsAnswer(command, null, null, null);
+ }
+ }
+}
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java
index 6e8ba30ea4a..96bb068c24f 100644
--- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java
@@ -659,25 +659,25 @@ public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool,
s_logger.info("Attempting to create volume " + name + " (" + pool.getType().toString() + ") in pool "
+ pool.getUuid() + " with size " + size);
- switch (pool.getType()){
- case RBD:
- return createPhysicalDiskOnRBD(name, pool, format, provisioningType, size);
- case NetworkFilesystem:
- case Filesystem:
- switch (format){
- case QCOW2:
- return createPhysicalDiskByQemuImg(name, pool, format, provisioningType, size);
- case RAW:
- return createPhysicalDiskByQemuImg(name, pool, format, provisioningType, size);
- case DIR:
- return createPhysicalDiskByLibVirt(name, pool, format, provisioningType, size);
- case TAR:
+ switch (pool.getType()) {
+ case RBD:
return createPhysicalDiskByLibVirt(name, pool, format, provisioningType, size);
+ case NetworkFilesystem:
+ case Filesystem:
+ switch (format) {
+ case QCOW2:
+ return createPhysicalDiskByQemuImg(name, pool, format, provisioningType, size);
+ case RAW:
+ return createPhysicalDiskByQemuImg(name, pool, format, provisioningType, size);
+ case DIR:
+ return createPhysicalDiskByLibVirt(name, pool, format, provisioningType, size);
+ case TAR:
+ return createPhysicalDiskByLibVirt(name, pool, format, provisioningType, size);
+ default:
+ throw new CloudRuntimeException("Unexpected disk format is specified.");
+ }
default:
- throw new CloudRuntimeException("Unexpected disk format is specified.");
- }
- default:
- return createPhysicalDiskByLibVirt(name, pool, format, provisioningType, size);
+ return createPhysicalDiskByLibVirt(name, pool, format, provisioningType, size);
}
}
@@ -748,50 +748,6 @@ private KVMPhysicalDisk createPhysicalDiskByQemuImg(String name, KVMStoragePool
return disk;
}
- private KVMPhysicalDisk createPhysicalDiskOnRBD(String name, KVMStoragePool pool,
- PhysicalDiskFormat format, Storage.ProvisioningType provisioningType, long size) {
- String volPath = null;
-
- /**
- * To have RBD function properly we want RBD images of format 2
- * libvirt currently defaults to format 1
- *
- * This has been fixed in libvirt 1.2.2, but that's not upstream
- * in all distributions
- *
- * For that reason we use the native RBD bindings to create the
- * RBD image until libvirt creates RBD format 2 by default
- */
-
- try {
- s_logger.info("Creating RBD image " + pool.getSourceDir() + "/" + name + " with size " + size);
-
- Rados r = new Rados(pool.getAuthUserName());
- r.confSet("mon_host", pool.getSourceHost() + ":" + pool.getSourcePort());
- r.confSet("key", pool.getAuthSecret());
- r.confSet("client_mount_timeout", "30");
- r.connect();
- s_logger.debug("Succesfully connected to Ceph cluster at " + r.confGet("mon_host"));
-
- IoCTX io = r.ioCtxCreate(pool.getSourceDir());
- Rbd rbd = new Rbd(io);
- rbd.create(name, size, rbdFeatures, rbdOrder);
-
- r.ioCtxDestroy(io);
- } catch (RadosException e) {
- throw new CloudRuntimeException(e.toString());
- } catch (RbdException e) {
- throw new CloudRuntimeException(e.toString());
- }
-
- volPath = pool.getSourceDir() + "/" + name;
- KVMPhysicalDisk disk = new KVMPhysicalDisk(volPath, name, pool);
- disk.setFormat(PhysicalDiskFormat.RAW);
- disk.setSize(size);
- disk.setVirtualSize(size);
- return disk;
- }
-
@Override
public boolean connectPhysicalDisk(String name, KVMStoragePool pool, Map<String, String> details) {
// this is for managed storage that needs to prep disks prior to use
diff --git a/plugins/hypervisors/kvm/src/org/apache/cloudstack/kvm/ha/KVMHAConfig.java b/plugins/hypervisors/kvm/src/org/apache/cloudstack/kvm/ha/KVMHAConfig.java
new file mode 100644
index 00000000000..59ea720328f
--- /dev/null
+++ b/plugins/hypervisors/kvm/src/org/apache/cloudstack/kvm/ha/KVMHAConfig.java
@@ -0,0 +1,56 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.kvm.ha;
+
+import org.apache.cloudstack.framework.config.ConfigKey;
+
+public class KVMHAConfig {
+
+ public static final ConfigKey<Long> KvmHAHealthCheckTimeout = new ConfigKey<>("Advanced", Long.class, "kvm.ha.health.check.timeout", "10",
+ "The maximum length of time, in seconds, expected for an health check to complete.", true, ConfigKey.Scope.Cluster);
+
+ public static final ConfigKey<Long> KvmHAActivityCheckTimeout = new ConfigKey<>("Advanced", Long.class, "kvm.ha.activity.check.timeout", "60",
+ "The maximum length of time, in seconds, expected for an activity check to complete.", true, ConfigKey.Scope.Cluster);
+
+ public static final ConfigKey<Long> KvmHAActivityCheckInterval = new ConfigKey<>("Advanced", Long.class, "kvm.ha.activity.check.interval", "60",
+ "The interval, in seconds, between activity checks.", true, ConfigKey.Scope.Cluster);
+
+ public static final ConfigKey<Long> KvmHAActivityCheckMaxAttempts = new ConfigKey<>("Advanced", Long.class, "kvm.ha.activity.check.max.attempts", "10",
+ "The maximum number of activity check attempts to perform before deciding to recover or degrade a resource.", true, ConfigKey.Scope.Cluster);
+
+ public static final ConfigKey<Double> KvmHAActivityCheckFailureThreshold = new ConfigKey<>("Advanced", Double.class, "kvm.ha.activity.check.failure.ratio", "0.7",
+ "The activity check failure threshold ratio. This is used with the activity check maximum attempts for deciding to recover or degrade a resource. For most environments, please keep this value above 0.5.",
+ true, ConfigKey.Scope.Cluster);
+
+ public static final ConfigKey<Long> KvmHADegradedMaxPeriod = new ConfigKey<>("Advanced", Long.class, "kvm.ha.degraded.max.period", "300",
+ "The maximum length of time, in seconds, a resource can be in degraded state where only health checks are performed.", true, ConfigKey.Scope.Cluster);
+
+ public static final ConfigKey<Long> KvmHARecoverTimeout = new ConfigKey<>("Advanced", Long.class, "kvm.ha.recover.timeout", "60",
+ "The maximum length of time, in seconds, expected for a recovery operation to complete.", true, ConfigKey.Scope.Cluster);
+
+ public static final ConfigKey<Long> KvmHARecoverWaitPeriod = new ConfigKey<>("Advanced", Long.class, "kvm.ha.recover.wait.period", "600",
+ "The maximum length of time, in seconds, to wait for a resource to recover.", true, ConfigKey.Scope.Cluster);
+
+ public static final ConfigKey<Long> KvmHARecoverAttemptThreshold = new ConfigKey<>("Advanced", Long.class, "kvm.ha.recover.failure.threshold", "1",
+ "The maximum recovery attempts to be made for a resource, after which the resource is fenced. The recovery counter resets when a health check passes for a resource.",
+ true, ConfigKey.Scope.Cluster);
+
+ public static final ConfigKey<Long> KvmHAFenceTimeout = new ConfigKey<>("Advanced", Long.class, "kvm.ha.fence.timeout", "60",
+ "The maximum length of time, in seconds, expected for a fence operation to complete.", true, ConfigKey.Scope.Cluster);
+
+}
diff --git a/plugins/hypervisors/kvm/src/org/apache/cloudstack/kvm/ha/KVMHAProvider.java b/plugins/hypervisors/kvm/src/org/apache/cloudstack/kvm/ha/KVMHAProvider.java
new file mode 100644
index 00000000000..5399fd23a1c
--- /dev/null
+++ b/plugins/hypervisors/kvm/src/org/apache/cloudstack/kvm/ha/KVMHAProvider.java
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cloudstack.kvm.ha;
+
+import com.cloud.host.Host;
+import com.cloud.hypervisor.Hypervisor;
+
+import org.apache.cloudstack.api.response.OutOfBandManagementResponse;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.Configurable;
+import org.apache.cloudstack.ha.HAResource;
+import org.apache.cloudstack.ha.provider.HACheckerException;
+import org.apache.cloudstack.ha.provider.HAFenceException;
+import org.apache.cloudstack.ha.provider.HAProvider;
+import org.apache.cloudstack.ha.provider.HARecoveryException;
+import org.apache.cloudstack.ha.provider.host.HAAbstractHostProvider;
+import org.apache.cloudstack.outofbandmanagement.OutOfBandManagement.PowerOperation;
+import org.apache.cloudstack.outofbandmanagement.OutOfBandManagementService;
+import org.apache.log4j.Logger;
+import org.joda.time.DateTime;
+
+import javax.inject.Inject;
+import java.security.InvalidParameterException;
+
+public final class KVMHAProvider extends HAAbstractHostProvider implements HAProvider<Host>, Configurable {
+ private final static Logger LOG = Logger.getLogger(KVMHAProvider.class);
+
+ @Inject
+ protected KVMHostActivityChecker hostActivityChecker;
+ @Inject
+ protected OutOfBandManagementService outOfBandManagementService;
+
+ @Override
+ public boolean isEligible(final Host host) {
+ if (outOfBandManagementService.isOutOfBandManagementEnabled(host)){
+ return !isInMaintenanceMode(host) && !isDisabled(host) &&
+ hostActivityChecker.getNeighbors(host).length > 0 &&
+ (Hypervisor.HypervisorType.KVM.equals(host.getHypervisorType()) ||
+ Hypervisor.HypervisorType.LXC.equals(host.getHypervisorType()));
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isHealthy(final Host r) throws HACheckerException {
+ return hostActivityChecker.isHealthy(r);
+ }
+
+ @Override
+ public boolean hasActivity(final Host r, final DateTime suspectTime) throws HACheckerException {
+ return hostActivityChecker.isActive(r, suspectTime);
+ }
+
+ @Override
+ public boolean recover(Host r) throws HARecoveryException {
+ try {
+ if (outOfBandManagementService.isOutOfBandManagementEnabled(r)){
+ final OutOfBandManagementResponse resp = outOfBandManagementService.executePowerOperation(r, PowerOperation.RESET, null);
+ return resp.getSuccess();
+ } else {
+ LOG.warn("OOBM recover operation failed for the host " + r.getName());
+ return false;
+ }
+ } catch (Exception e){
+ LOG.warn("OOBM service is not configured or enabled for this host " + r.getName() + " error is " + e.getMessage());
+ throw new HARecoveryException(" OOBM service is not configured or enabled for this host " + r.getName(), e);
+ }
+ }
+
+ @Override
+ public boolean fence(Host r) throws HAFenceException {
+ try {
+ if (outOfBandManagementService.isOutOfBandManagementEnabled(r)){
+ final OutOfBandManagementResponse resp = outOfBandManagementService.executePowerOperation(r, PowerOperation.OFF, null);
+ return resp.getSuccess();
+ } else {
+ LOG.warn("OOBM fence operation failed for this host " + r.getName());
+ return false;
+ }
+ } catch (Exception e){
+ LOG.warn("OOBM service is not configured or enabled for this host " + r.getName() + " error is " + e.getMessage());
+ throw new HAFenceException("OOBM service is not configured or enabled for this host " + r.getName() , e);
+ }
+ }
+
+ @Override
+ public HAResource.ResourceSubType resourceSubType() {
+ return HAResource.ResourceSubType.KVM;
+ }
+
+ @Override
+ public Object getConfigValue(final HAProviderConfig name, final Host host) {
+ final Long clusterId = host.getClusterId();
+ switch (name) {
+ case HealthCheckTimeout:
+ return KVMHAConfig.KvmHAHealthCheckTimeout.valueIn(clusterId);
+ case ActivityCheckTimeout:
+ return KVMHAConfig.KvmHAActivityCheckTimeout.valueIn(clusterId);
+ case MaxActivityCheckInterval:
+ return KVMHAConfig.KvmHAActivityCheckInterval.valueIn(clusterId);
+ case MaxActivityChecks:
+ return KVMHAConfig.KvmHAActivityCheckMaxAttempts.valueIn(clusterId);
+ case ActivityCheckFailureRatio:
+ return KVMHAConfig.KvmHAActivityCheckFailureThreshold.valueIn(clusterId);
+ case RecoveryWaitTimeout:
+ return KVMHAConfig.KvmHARecoverWaitPeriod.valueIn(clusterId);
+ case RecoveryTimeout:
+ return KVMHAConfig.KvmHARecoverTimeout.valueIn(clusterId);
+ case FenceTimeout:
+ return KVMHAConfig.KvmHAFenceTimeout.valueIn(clusterId);
+ case MaxRecoveryAttempts:
+ return KVMHAConfig.KvmHARecoverAttemptThreshold.valueIn(clusterId);
+ case MaxDegradedWaitTimeout:
+ return KVMHAConfig.KvmHADegradedMaxPeriod.valueIn(clusterId);
+ default:
+ throw new InvalidParameterException("Unknown HAProviderConfig " + name.toString());
+ }
+ }
+
+ @Override
+ public String getConfigComponentName() {
+ return KVMHAConfig.class.getSimpleName();
+ }
+
+ @Override
+ public ConfigKey<?>[] getConfigKeys() {
+ return new ConfigKey<?>[] {
+ KVMHAConfig.KvmHAHealthCheckTimeout,
+ KVMHAConfig.KvmHAActivityCheckTimeout,
+ KVMHAConfig.KvmHARecoverTimeout,
+ KVMHAConfig.KvmHAFenceTimeout,
+ KVMHAConfig.KvmHAActivityCheckInterval,
+ KVMHAConfig.KvmHAActivityCheckMaxAttempts,
+ KVMHAConfig.KvmHAActivityCheckFailureThreshold,
+ KVMHAConfig.KvmHADegradedMaxPeriod,
+ KVMHAConfig.KvmHARecoverWaitPeriod,
+ KVMHAConfig.KvmHARecoverAttemptThreshold
+ };
+ }
+}
diff --git a/plugins/hypervisors/kvm/src/org/apache/cloudstack/kvm/ha/KVMHostActivityChecker.java b/plugins/hypervisors/kvm/src/org/apache/cloudstack/kvm/ha/KVMHostActivityChecker.java
new file mode 100644
index 00000000000..060b484fec7
--- /dev/null
+++ b/plugins/hypervisors/kvm/src/org/apache/cloudstack/kvm/ha/KVMHostActivityChecker.java
@@ -0,0 +1,205 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.kvm.ha;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.CheckOnHostCommand;
+import com.cloud.agent.api.CheckVMActivityOnStoragePoolCommand;
+import com.cloud.exception.StorageUnavailableException;
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+import com.cloud.host.Status;
+import com.cloud.hypervisor.Hypervisor;
+import com.cloud.resource.ResourceManager;
+import com.cloud.storage.StorageManager;
+import com.cloud.storage.StoragePool;
+import com.cloud.storage.Volume;
+import com.cloud.storage.VolumeVO;
+import com.cloud.storage.dao.VolumeDao;
+import com.cloud.utils.component.AdapterBase;
+import com.cloud.vm.VMInstanceVO;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.dao.VMInstanceDao;
+import org.apache.cloudstack.ha.provider.ActivityCheckerInterface;
+import org.apache.cloudstack.ha.provider.HACheckerException;
+import org.apache.cloudstack.ha.provider.HealthCheckerInterface;
+import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.log4j.Logger;
+
+import javax.inject.Inject;
+import java.util.ArrayList;
+import org.joda.time.DateTime;
+import java.util.HashMap;
+import java.util.List;
+
+public class KVMHostActivityChecker extends AdapterBase implements ActivityCheckerInterface<Host>, HealthCheckerInterface<Host> {
+ private final static Logger LOG = Logger.getLogger(KVMHostActivityChecker.class);
+
+ @Inject
+ private VolumeDao volumeDao;
+ @Inject
+ private VMInstanceDao vmInstanceDao;
+ @Inject
+ private AgentManager agentMgr;
+ @Inject
+ private PrimaryDataStoreDao storagePool;
+ @Inject
+ private StorageManager storageManager;
+ @Inject
+ private ResourceManager resourceManager;
+
+ @Override
+ public boolean isActive(Host r, DateTime suspectTime) throws HACheckerException {
+ try {
+ return isVMActivtyOnHost(r, suspectTime);
+ }
+ catch (StorageUnavailableException e){
+ throw new HACheckerException("Storage is unavailable to do the check, mostly host is not reachable ", e);
+ }
+ catch (Exception e){
+ throw new HACheckerException("Operation timed out, mostly host is not reachable ", e);
+ }
+ }
+
+ @Override
+ public boolean isHealthy(Host r) {
+ return isAgentActive(r);
+ }
+
+ private boolean isAgentActive(Host agent) {
+ if (agent.getHypervisorType() != Hypervisor.HypervisorType.KVM && agent.getHypervisorType() != Hypervisor.HypervisorType.LXC) {
+ throw new IllegalStateException("Calling KVM investigator for non KVM Host of type " + agent.getHypervisorType());
+ }
+ Status hostStatus = Status.Unknown;
+ Status neighbourStatus = Status.Unknown;
+ final CheckOnHostCommand cmd = new CheckOnHostCommand(agent);
+ try {
+ Answer answer = agentMgr.easySend(agent.getId(), cmd);
+ if (answer != null) {
+ hostStatus = answer.getResult() ? Status.Down : Status.Up;
+ if ( hostStatus == Status.Up ){
+ return true;
+ }
+ }
+ else {
+ hostStatus = Status.Disconnected;
+ }
+ } catch (Exception e) {
+ LOG.warn("Failed to send command to host: " + agent.getId());
+ }
+
+ List<HostVO> neighbors = resourceManager.listHostsInClusterByStatus(agent.getClusterId(), Status.Up);
+ for (HostVO neighbor : neighbors) {
+ if (neighbor.getId() == agent.getId() || (neighbor.getHypervisorType() != Hypervisor.HypervisorType.KVM && neighbor.getHypervisorType() != Hypervisor.HypervisorType.LXC)) {
+ continue;
+ }
+ if (LOG.isTraceEnabled()){
+ LOG.trace("Investigating host:" + agent.getId() + " via neighbouring host:" + neighbor.getId());
+ }
+ try {
+ Answer answer = agentMgr.easySend(neighbor.getId(), cmd);
+ if (answer != null) {
+ neighbourStatus = answer.getResult() ? Status.Down : Status.Up;
+ if (LOG.isTraceEnabled()){
+ LOG.trace("Neighbouring host:" + neighbor.getId() + " returned status:" + neighbourStatus + " for the investigated host:" + agent.getId());
+ }
+ if (neighbourStatus == Status.Up) {
+ break;
+ }
+ }
+ } catch (Exception e) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Failed to send command to host: " + neighbor.getId());
+ }
+ }
+ }
+ if (neighbourStatus == Status.Up && (hostStatus == Status.Disconnected || hostStatus == Status.Down)) {
+ hostStatus = Status.Disconnected;
+ }
+ if (neighbourStatus == Status.Down && (hostStatus == Status.Disconnected || hostStatus == Status.Down)) {
+ hostStatus = Status.Down;
+ }
+
+ if (LOG.isTraceEnabled()){
+ LOG.trace("Resource state = " + hostStatus.name());
+ }
+ return hostStatus == Status.Up;
+ }
+
+ private boolean isVMActivtyOnHost(Host agent, DateTime suspectTime) throws StorageUnavailableException {
+ if (agent.getHypervisorType() != Hypervisor.HypervisorType.KVM && agent.getHypervisorType() != Hypervisor.HypervisorType.LXC) {
+ throw new IllegalStateException("Calling KVM investigator for non KVM Host of type " + agent.getHypervisorType());
+ }
+ boolean activityStatus = true;
+ HashMap<StoragePool, List<Volume>> poolVolMap = getVolumeUuidOnHost(agent);
+ for (StoragePool pool : poolVolMap.keySet()) {
+ //for each storage pool find activity
+ List<Volume> volume_list = poolVolMap.get(pool);
+ final CheckVMActivityOnStoragePoolCommand cmd = new CheckVMActivityOnStoragePoolCommand(agent, pool, volume_list, suspectTime);
+ //send the command to appropriate storage pool
+ Answer answer = storageManager.sendToPool(pool, getNeighbors(agent), cmd);
+ if (answer != null) {
+ activityStatus = ! answer.getResult();
+ } else {
+ throw new IllegalStateException("Did not get a valid response for VM activity check for host " + agent.getId());
+ }
+ }
+ if (LOG.isDebugEnabled()){
+ LOG.debug("Resource active = " + activityStatus);
+ }
+ return activityStatus;
+ }
+
+ private HashMap<StoragePool, List<Volume>> getVolumeUuidOnHost(Host agent) {
+ List<VMInstanceVO> vm_list = vmInstanceDao.listByHostId(agent.getId());
+ List<VolumeVO> volume_list = new ArrayList<VolumeVO>();
+ for (VirtualMachine vm : vm_list) {
+ List<VolumeVO> vm_volume_list = volumeDao.findByInstance(vm.getId());
+ volume_list.addAll(vm_volume_list);
+ }
+
+ HashMap<StoragePool, List<Volume>> poolVolMap = new HashMap<StoragePool, List<Volume>>();
+ for (Volume vol : volume_list) {
+ StoragePool sp = storagePool.findById(vol.getPoolId());
+ if (!poolVolMap.containsKey(sp)) {
+ List<Volume> list = new ArrayList<Volume>();
+ list.add(vol);
+
+ poolVolMap.put(sp, list);
+ } else {
+ poolVolMap.get(sp).add(vol);
+ }
+ }
+ return poolVolMap;
+ }
+
+ public long[] getNeighbors(Host agent) {
+ List<Long> neighbors = new ArrayList<Long>();
+ List<HostVO> cluster_hosts = resourceManager.listHostsInClusterByStatus(agent.getClusterId(), Status.Up);
+ for (HostVO host : cluster_hosts) {
+ if (host.getId() == agent.getId() || (host.getHypervisorType() != Hypervisor.HypervisorType.KVM && host.getHypervisorType() != Hypervisor.HypervisorType.LXC)) {
+ continue;
+ }
+ neighbors.add(host.getId());
+ }
+ return ArrayUtils.toPrimitive(neighbors.toArray(new Long[neighbors.size()]));
+ }
+
+}
diff --git a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java
index 8992a5b2430..b3f85300321 100644
--- a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java
+++ b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java
@@ -366,6 +366,9 @@ The configure() method of LibvirtComputingResource has not been called, so the d
assertXpath(domainDoc, "/domain/on_reboot/text()", "restart");
assertXpath(domainDoc, "/domain/on_poweroff/text()", "destroy");
assertXpath(domainDoc, "/domain/on_crash/text()", "destroy");
+
+ assertXpath(domainDoc, "/domain/devices/watchdog/@model", "i6300esb");
+ assertXpath(domainDoc, "/domain/devices/watchdog/@action", "none");
}
static Document parse(final String input) {
diff --git a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtDomainXMLParserTest.java b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtDomainXMLParserTest.java
index f32f7fd833d..78c4e868f2c 100644
--- a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtDomainXMLParserTest.java
+++ b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtDomainXMLParserTest.java
@@ -27,6 +27,7 @@
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.RngDef;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.ChannelDef;
+import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.WatchDogDef;
public class LibvirtDomainXMLParserTest extends TestCase {
@@ -185,6 +186,7 @@ public void testDomainXMLParser() {
"<alias name='channel0'/>" +
"<address type='virtio-serial' controller='0' bus='0' port='1'/>" +
"</channel>" +
+ "<watchdog model='i6300esb' action='reset'/>" +
"</devices>" +
"<seclabel type='none'/>" +
"</domain>";
@@ -232,5 +234,9 @@ public void testDomainXMLParser() {
assertEquals(RngDef.RngBackendModel.RANDOM, rngs.get(0).getRngBackendModel());
assertEquals(4096, rngs.get(0).getRngRateBytes());
assertEquals(5000, rngs.get(0).getRngRatePeriod());
+
+ List<WatchDogDef> watchDogs = parser.getWatchDogs();
+ assertEquals(WatchDogDef.WatchDogModel.I6300ESB, watchDogs.get(0).getModel());
+ assertEquals(WatchDogDef.WatchDogAction.RESET, watchDogs.get(0).getAction());
}
}
diff --git a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java
index b8ecdc3c2e3..8f0f93d31ab 100644
--- a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java
+++ b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java
@@ -149,4 +149,13 @@ public void testChannelDef() {
assertEquals(path, channelDef.getPath());
}
+ public void testWatchDogDef() {
+ LibvirtVMDef.WatchDogDef.WatchDogModel model = LibvirtVMDef.WatchDogDef.WatchDogModel.I6300ESB;
+ LibvirtVMDef.WatchDogDef.WatchDogAction action = LibvirtVMDef.WatchDogDef.WatchDogAction.RESET;
+
+ LibvirtVMDef.WatchDogDef def = new LibvirtVMDef.WatchDogDef(action, model);
+ assertEquals(def.getModel(), model);
+ assertEquals(def.getAction(), action);
+ }
+
}
diff --git a/plugins/hypervisors/kvm/test/org/apache/cloudstack/kvm/ha/KVMHostHATest.java b/plugins/hypervisors/kvm/test/org/apache/cloudstack/kvm/ha/KVMHostHATest.java
new file mode 100644
index 00000000000..26b7e6ae206
--- /dev/null
+++ b/plugins/hypervisors/kvm/test/org/apache/cloudstack/kvm/ha/KVMHostHATest.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cloudstack.kvm.ha;
+
+import com.cloud.exception.StorageUnavailableException;
+import com.cloud.host.Host;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import org.apache.cloudstack.ha.provider.HACheckerException;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+import org.joda.time.DateTime;
+
+@RunWith(MockitoJUnitRunner.class)
+public class KVMHostHATest {
+
+ @Mock
+ private Host host;
+ @Mock
+ private KVMHostActivityChecker kvmHostActivityChecker;
+ private KVMHAProvider kvmHAProvider;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ kvmHAProvider = new KVMHAProvider();
+ kvmHAProvider.hostActivityChecker = kvmHostActivityChecker;
+ }
+
+ @Test
+ public void testHostActivityForHealthyHost() throws HACheckerException, StorageUnavailableException {
+ when(host.getHypervisorType()).thenReturn(HypervisorType.KVM);
+ when(kvmHostActivityChecker.isHealthy(host)).thenReturn(true);
+ assertTrue(kvmHAProvider.isHealthy(host));
+ }
+
+ @Test
+ public void testHostActivityForUnHealthyHost() throws HACheckerException, StorageUnavailableException {
+ when(host.getHypervisorType()).thenReturn(HypervisorType.KVM);
+ when(kvmHostActivityChecker.isHealthy(host)).thenReturn(false);
+ assertFalse(kvmHAProvider.isHealthy(host));
+ }
+
+ @Test
+ public void testHostActivityForActiveHost() throws HACheckerException, StorageUnavailableException {
+ when(host.getHypervisorType()).thenReturn(HypervisorType.KVM);
+ DateTime dt = new DateTime();
+ when(kvmHostActivityChecker.isActive(host, dt)).thenReturn(true);
+ assertTrue(kvmHAProvider.hasActivity(host, dt));
+ }
+
+ @Test
+ public void testHostActivityForDownHost() throws HACheckerException, StorageUnavailableException {
+ when(host.getHypervisorType()).thenReturn(HypervisorType.KVM);
+ DateTime dt = new DateTime();
+ when(kvmHostActivityChecker.isActive(host, dt)).thenReturn(false);
+ assertFalse(kvmHAProvider.hasActivity(host, dt));
+ }
+
+}
diff --git a/plugins/hypervisors/ovm/pom.xml b/plugins/hypervisors/ovm/pom.xml
index d99b3f92b5a..f4a1ef7c012 100644
--- a/plugins/hypervisors/ovm/pom.xml
+++ b/plugins/hypervisors/ovm/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/hypervisors/ovm3/pom.xml b/plugins/hypervisors/ovm3/pom.xml
index 72afe8b0002..b73aec47566 100644
--- a/plugins/hypervisors/ovm3/pom.xml
+++ b/plugins/hypervisors/ovm3/pom.xml
@@ -23,15 +23,10 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
- <dependency>
- <groupId>xml-apis</groupId>
- <artifactId>xml-apis</artifactId>
- <version>${cs.xml-apis.version}</version>
- </dependency>
<dependency>
<groupId>org.apache.xmlrpc</groupId>
<artifactId>xmlrpc-client</artifactId>
diff --git a/plugins/hypervisors/simulator/pom.xml b/plugins/hypervisors/simulator/pom.xml
index b6a5b384e7f..a49679e082d 100644
--- a/plugins/hypervisors/simulator/pom.xml
+++ b/plugins/hypervisors/simulator/pom.xml
@@ -22,7 +22,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>cloud-plugin-hypervisor-simulator</artifactId>
@@ -63,5 +63,10 @@
<artifactId>cloud-engine-storage-snapshot</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>${cs.guava.version}</version>
+ </dependency>
</dependencies>
</project>
diff --git a/plugins/hypervisors/simulator/resources/META-INF/cloudstack/simulator-compute/spring-simulator-compute-context.xml b/plugins/hypervisors/simulator/resources/META-INF/cloudstack/simulator-compute/spring-simulator-compute-context.xml
index c95e4bbba26..5b779f7a398 100644
--- a/plugins/hypervisors/simulator/resources/META-INF/cloudstack/simulator-compute/spring-simulator-compute-context.xml
+++ b/plugins/hypervisors/simulator/resources/META-INF/cloudstack/simulator-compute/spring-simulator-compute-context.xml
@@ -36,4 +36,8 @@
<bean id="SimulatorFencer" class="com.cloud.ha.SimulatorFencer">
<property name="name" value="Simulator Fencer"/>
</bean>
+
+ <bean id="SimulatorHAProvider" class="org.apache.cloudstack.ha.SimulatorHAProvider">
+ <property name="name" value="SimulatorHAProvider" />
+ </bean>
</beans>
diff --git a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockAgentManager.java b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockAgentManager.java
index 0851023a7ef..3a315509b49 100644
--- a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockAgentManager.java
+++ b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockAgentManager.java
@@ -20,6 +20,9 @@
import javax.naming.ConfigurationException;
+import org.apache.cloudstack.ca.SetupCertificateCommand;
+import org.apache.cloudstack.ca.SetupKeyStoreCommand;
+
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.CheckHealthCommand;
import com.cloud.agent.api.CheckNetworkCommand;
@@ -52,6 +55,10 @@ boolean handleSystemVMStart(long vmId, String privateIpAddress, String privateMa
Answer pingTest(PingTestCommand cmd);
+ Answer setupKeyStore(SetupKeyStoreCommand cmd);
+
+ Answer setupCertificate(SetupCertificateCommand cmd);
+
MockHost getHost(String guid);
Answer maintain(MaintainCommand cmd);
diff --git a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java
index 9211214ccdc..9d1e4079d42 100644
--- a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java
+++ b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java
@@ -31,7 +31,10 @@
import javax.inject.Inject;
import javax.naming.ConfigurationException;
-import com.cloud.user.AccountManager;
+import org.apache.cloudstack.ca.SetupCertificateAnswer;
+import org.apache.cloudstack.ca.SetupCertificateCommand;
+import org.apache.cloudstack.ca.SetupKeyStoreCommand;
+import org.apache.cloudstack.ca.SetupKeystoreAnswer;
import org.apache.cloudstack.context.CallContext;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@@ -62,6 +65,7 @@
import com.cloud.simulator.MockVMVO;
import com.cloud.simulator.dao.MockHostDao;
import com.cloud.simulator.dao.MockVMDao;
+import com.cloud.user.AccountManager;
import com.cloud.utils.Pair;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.concurrency.NamedThreadFactory;
@@ -459,6 +463,24 @@ public Answer pingTest(PingTestCommand cmd) {
return new Answer(cmd);
}
+ @Override
+ public Answer setupKeyStore(SetupKeyStoreCommand cmd) {
+ return new SetupKeystoreAnswer(
+ "-----BEGIN CERTIFICATE REQUEST-----\n" +
+ "MIIBHjCByQIBADBkMQswCQYDVQQGEwJJTjELMAkGA1UECAwCSFIxETAPBgNVBAcM\n" +
+ "CEd1cnVncmFtMQ8wDQYDVQQKDAZBcGFjaGUxEzARBgNVBAsMCkNsb3VkU3RhY2sx\n" +
+ "DzANBgNVBAMMBnYtMS1WTTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQD46KFWKYrJ\n" +
+ "F43Y1oqWUfrl4mj4Qm05Bgsi6nuigZv7ufiAKK0nO4iJKdRa2hFMUvBi2/bU3IyY\n" +
+ "Nvg7cdJsn4K9AgMBAAGgADANBgkqhkiG9w0BAQUFAANBAIta9glu/ZSjA/ncyXix\n" +
+ "yDOyAKmXXxsRIsdrEuIzakUuJS7C8IG0FjUbDyIaiwWQa5x+Lt4oMqCmpNqRzaGP\n" +
+ "fOo=\n" + "-----END CERTIFICATE REQUEST-----");
+ }
+
+ @Override
+ public Answer setupCertificate(SetupCertificateCommand cmd) {
+ return new SetupCertificateAnswer(true);
+ }
+
@Override
public boolean start() {
for (Discoverer discoverer : discoverers) {
diff --git a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/SimulatorManagerImpl.java b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/SimulatorManagerImpl.java
index 03593392ba7..ae06a12ad70 100644
--- a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/SimulatorManagerImpl.java
+++ b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/SimulatorManagerImpl.java
@@ -26,6 +26,8 @@
import javax.inject.Inject;
import javax.naming.ConfigurationException;
+import org.apache.cloudstack.ca.SetupCertificateCommand;
+import org.apache.cloudstack.ca.SetupKeyStoreCommand;
import org.apache.cloudstack.storage.command.DeleteCommand;
import org.apache.cloudstack.storage.command.DownloadCommand;
import org.apache.cloudstack.storage.command.DownloadProgressCommand;
@@ -110,6 +112,8 @@
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
import com.cloud.api.commands.CleanupSimulatorMockCmd;
import com.cloud.api.commands.ConfigureSimulatorCmd;
+import com.cloud.api.commands.ConfigureSimulatorHAProviderState;
+import com.cloud.api.commands.ListSimulatorHAStateTransitions;
import com.cloud.api.commands.QuerySimulatorMockCmd;
import com.cloud.resource.SimulatorStorageProcessor;
import com.cloud.serializer.GsonHelper;
@@ -191,6 +195,8 @@ public MockAgentManager getAgentMgr() {
cmdList.add(ConfigureSimulatorCmd.class);
cmdList.add(QuerySimulatorMockCmd.class);
cmdList.add(CleanupSimulatorMockCmd.class);
+ cmdList.add(ConfigureSimulatorHAProviderState.class);
+ cmdList.add(ListSimulatorHAStateTransitions.class);
return cmdList;
}
@@ -280,6 +286,10 @@ public Answer simulate(final Command cmd, final String hostGuid) {
answer = _mockAgentMgr.checkHealth((CheckHealthCommand)cmd);
} else if (cmd instanceof PingTestCommand) {
answer = _mockAgentMgr.pingTest((PingTestCommand)cmd);
+ } else if (cmd instanceof SetupKeyStoreCommand) {
+ answer = _mockAgentMgr.setupKeyStore((SetupKeyStoreCommand)cmd);
+ } else if (cmd instanceof SetupCertificateCommand) {
+ answer = _mockAgentMgr.setupCertificate((SetupCertificateCommand)cmd);
} else if (cmd instanceof PrepareForMigrationCommand) {
answer = _mockVmMgr.prepareForMigrate((PrepareForMigrationCommand)cmd);
} else if (cmd instanceof MigrateCommand) {
diff --git a/plugins/hypervisors/simulator/src/com/cloud/api/commands/ConfigureSimulatorHAProviderState.java b/plugins/hypervisors/simulator/src/com/cloud/api/commands/ConfigureSimulatorHAProviderState.java
new file mode 100644
index 00000000000..1d68a184a5a
--- /dev/null
+++ b/plugins/hypervisors/simulator/src/com/cloud/api/commands/ConfigureSimulatorHAProviderState.java
@@ -0,0 +1,120 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package com.cloud.api.commands;
+
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.host.Host;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiArgValidator;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.HostResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.ha.HAManager;
+import org.apache.cloudstack.ha.SimulatorHAProvider;
+import org.apache.cloudstack.ha.SimulatorHAState;
+
+import javax.inject.Inject;
+
+@APICommand(name = ConfigureSimulatorHAProviderState.APINAME,
+ description="configures simulator HA provider state for a host for probing and testing",
+ responseObject=SuccessResponse.class,
+ since = "4.11", authorized = {RoleType.Admin})
+public final class ConfigureSimulatorHAProviderState extends BaseCmd {
+ public static final String APINAME = "configureSimulatorHAProviderState";
+
+ @Inject
+ private HAManager haManager;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.HOST_ID, type = BaseCmd.CommandType.UUID, entityType = HostResponse.class,
+ description = "List by host ID", required = true, validations = {ApiArgValidator.PositiveNumber})
+ private Long hostId;
+
+ @Parameter(name = ApiConstants.HEALTH, type = CommandType.BOOLEAN,
+ description = "Set true is haprovider for simulator host should be healthy",
+ required = true)
+ private Boolean healthy;
+
+ @Parameter(name = ApiConstants.ACTIVITY, type = CommandType.BOOLEAN,
+ description = "Set true is haprovider for simulator host should have activity",
+ required = true)
+ private Boolean activity;
+
+ @Parameter(name = ApiConstants.RECOVER, type = CommandType.BOOLEAN,
+ description = "Set true is haprovider for simulator host should be be recoverable",
+ required = true)
+ private Boolean recovery;
+
+ @Parameter(name = ApiConstants.FENCE, type = CommandType.BOOLEAN,
+ description = "Set true is haprovider for simulator host should be be fence-able",
+ required = true)
+ private Boolean fenceable;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getHostId() {
+ return hostId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
+ final Host host = _resourceService.getHost(getHostId());
+ if (host == null) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to find host by ID: " + getHostId());
+ }
+ final SimulatorHAState haState = new SimulatorHAState(healthy, activity, recovery, fenceable);
+ final SimulatorHAProvider simulatorHAProvider = (SimulatorHAProvider) haManager.getHAProvider(SimulatorHAProvider.class.getSimpleName().toLowerCase());
+ if (simulatorHAProvider != null) {
+ simulatorHAProvider.setHAStateForHost(host.getId(), haState);
+ }
+ final SuccessResponse response = new SuccessResponse();
+ response.setSuccess(simulatorHAProvider != null);
+ response.setResponseName(getCommandName());
+ response.setObjectName("simulatorhaprovider");
+ setResponseObject(response);
+ }
+
+ @Override
+ public String getCommandName() {
+ return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccountId();
+ }
+}
diff --git a/plugins/hypervisors/simulator/src/com/cloud/api/commands/ListSimulatorHAStateTransitions.java b/plugins/hypervisors/simulator/src/com/cloud/api/commands/ListSimulatorHAStateTransitions.java
new file mode 100644
index 00000000000..52368747523
--- /dev/null
+++ b/plugins/hypervisors/simulator/src/com/cloud/api/commands/ListSimulatorHAStateTransitions.java
@@ -0,0 +1,104 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package com.cloud.api.commands;
+
+import com.cloud.api.response.SimulatorHAStateResponse;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.host.Host;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiArgValidator;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.HostResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.ha.HAManager;
+import org.apache.cloudstack.ha.SimulatorHAProvider;
+
+import javax.inject.Inject;
+import java.util.ArrayList;
+import java.util.List;
+
+@APICommand(name = ListSimulatorHAStateTransitions.APINAME,
+ description="list recent simulator HA state transitions for a host for probing and testing",
+ responseObject=SimulatorHAStateResponse.class,
+ since = "4.11", authorized = {RoleType.Admin})
+public final class ListSimulatorHAStateTransitions extends BaseListCmd {
+ public static final String APINAME = "listSimulatorHAStateTransitions";
+
+ @Inject
+ private HAManager haManager;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.HOST_ID, type = BaseCmd.CommandType.UUID, entityType = HostResponse.class,
+ description = "List by host ID", required = true, validations = {ApiArgValidator.PositiveNumber})
+ private Long hostId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getHostId() {
+ return hostId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
+ final Host host = _resourceService.getHost(getHostId());
+ if (host == null) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to find host by ID: " + getHostId());
+ }
+
+ final SimulatorHAProvider simulatorHAProvider = (SimulatorHAProvider) haManager.getHAProvider(SimulatorHAProvider.class.getSimpleName().toLowerCase());
+ List<SimulatorHAStateResponse> recentStates = new ArrayList<>();
+ if (simulatorHAProvider != null) {
+ recentStates = simulatorHAProvider.listHAStateTransitions(host.getId());
+ }
+ final ListResponse<SimulatorHAStateResponse> response = new ListResponse<>();
+ response.setResponses(recentStates);
+ response.setResponseName(getCommandName());
+ response.setObjectName("simulatorhastatetransition");
+ setResponseObject(response);
+ }
+
+ @Override
+ public String getCommandName() {
+ return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccountId();
+ }
+}
diff --git a/plugins/hypervisors/simulator/src/com/cloud/api/response/SimulatorHAStateResponse.java b/plugins/hypervisors/simulator/src/com/cloud/api/response/SimulatorHAStateResponse.java
new file mode 100644
index 00000000000..47481ad605f
--- /dev/null
+++ b/plugins/hypervisors/simulator/src/com/cloud/api/response/SimulatorHAStateResponse.java
@@ -0,0 +1,65 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package com.cloud.api.response;
+
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseResponse;
+import org.apache.cloudstack.ha.HAConfig;
+
+public class SimulatorHAStateResponse extends BaseResponse {
+ @SerializedName(ApiConstants.HA_STATE) @Param(description="the ha state")
+ private String haState;
+
+ @SerializedName("prevhastate") @Param(description="the previous ha state")
+ private String previousHaState;
+
+ @SerializedName("event") @Param(description="the event that caused state transition")
+ private String haEvent;
+
+ @SerializedName("activitycounter") @Param(description="the activity counter")
+ private Long activityCounter;
+
+ @SerializedName("recoverycounter") @Param(description="the recovery counter")
+ private Long recoveryCounter;
+
+ public void setHaState(final HAConfig.HAState haState) {
+ if (haState != null) {
+ this.haState = haState.toString().toLowerCase();
+ }
+ }
+
+ public void setPreviousHaState(final HAConfig.HAState previousHaState) {
+ if (previousHaState != null) {
+ this.previousHaState = previousHaState.toString().toLowerCase();
+ }
+ }
+
+ public void setHaEvent(final HAConfig.Event haEvent) {
+ this.haEvent = haEvent.toString().toLowerCase();
+ }
+
+ public void setActivityCounter(Long activityCounter) {
+ this.activityCounter = activityCounter;
+ }
+
+ public void setRecoveryCounter(Long recoveryCounter) {
+ this.recoveryCounter = recoveryCounter;
+ }
+}
diff --git a/plugins/hypervisors/simulator/src/com/cloud/ha/SimulatorInvestigator.java b/plugins/hypervisors/simulator/src/com/cloud/ha/SimulatorInvestigator.java
index aa40f1bb28d..8996d5af91c 100644
--- a/plugins/hypervisors/simulator/src/com/cloud/ha/SimulatorInvestigator.java
+++ b/plugins/hypervisors/simulator/src/com/cloud/ha/SimulatorInvestigator.java
@@ -21,6 +21,7 @@
import javax.inject.Inject;
import org.apache.log4j.Logger;
+import org.apache.cloudstack.ha.HAManager;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
@@ -48,6 +49,8 @@
ResourceManager _resourceMgr;
@Inject
MockConfigurationDao _mockConfigDao;
+ @Inject
+ private HAManager haManager;
protected SimulatorInvestigator() {
}
@@ -58,6 +61,10 @@ public Status isAgentAlive(Host agent) {
return null;
}
+ if (haManager.isHAEligible(agent)) {
+ return haManager.getHostStatus(agent);
+ }
+
CheckOnHostCommand cmd = new CheckOnHostCommand(agent);
List<HostVO> neighbors = _resourceMgr.listHostsInClusterByStatus(agent.getClusterId(), Status.Up);
for (HostVO neighbor : neighbors) {
@@ -79,6 +86,9 @@ public Status isAgentAlive(Host agent) {
@Override
public boolean isVmAlive(VirtualMachine vm, Host host) throws UnknownVM {
+ if (haManager.isHAEligible(host)) {
+ return haManager.isVMAliveOnHost(host);
+ }
CheckVirtualMachineCommand cmd = new CheckVirtualMachineCommand(vm.getInstanceName());
try {
Answer answer = _agentMgr.send(vm.getHostId(), cmd);
diff --git a/plugins/hypervisors/simulator/src/org/apache/cloudstack/ha/SimulatorHAProvider.java b/plugins/hypervisors/simulator/src/org/apache/cloudstack/ha/SimulatorHAProvider.java
new file mode 100644
index 00000000000..1189e9a5e1f
--- /dev/null
+++ b/plugins/hypervisors/simulator/src/org/apache/cloudstack/ha/SimulatorHAProvider.java
@@ -0,0 +1,160 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ha;
+
+import com.cloud.api.response.SimulatorHAStateResponse;
+import com.cloud.host.Host;
+import com.cloud.hypervisor.Hypervisor;
+import com.cloud.utils.fsm.StateListener;
+import com.cloud.utils.fsm.StateMachine2;
+import org.apache.cloudstack.ha.provider.HACheckerException;
+import org.apache.cloudstack.ha.provider.HAFenceException;
+import org.apache.cloudstack.ha.provider.HAProvider;
+import org.apache.cloudstack.ha.provider.HARecoveryException;
+import org.apache.cloudstack.ha.provider.host.HAAbstractHostProvider;
+import org.joda.time.DateTime;
+
+import javax.inject.Inject;
+import java.security.InvalidParameterException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class SimulatorHAProvider extends HAAbstractHostProvider implements HAProvider<Host>, StateListener<HAConfig.HAState, HAConfig.Event, HAConfig> {
+
+ @Inject
+ private HAManager haManager;
+
+ private final Map<Long, SimulatorHAState> hostHAStateMap = new ConcurrentHashMap<>();
+
+ public SimulatorHAProvider() {
+ HAConfig.HAState.getStateMachine().registerListener(this);
+ }
+
+ public void setHAStateForHost(final Long hostId, final SimulatorHAState state) {
+ hostHAStateMap.put(hostId, state);
+ haManager.purgeHACounter(hostId, HAResource.ResourceType.Host);
+ }
+
+ public List<SimulatorHAStateResponse> listHAStateTransitions(final Long hostId) {
+ final SimulatorHAState haState = hostHAStateMap.get(hostId);
+ if (haState == null) {
+ return Collections.emptyList();
+ }
+ return haState.listRecentStateTransitions();
+ }
+
+ @Override
+ public HAResource.ResourceType resourceType() {
+ return HAResource.ResourceType.Host;
+ }
+
+ @Override
+ public HAResource.ResourceSubType resourceSubType() {
+ return HAResource.ResourceSubType.Simulator;
+ }
+
+ @Override
+ public boolean isEligible(final Host host) {
+ if (host == null) {
+ return false;
+ }
+ final SimulatorHAState haState = hostHAStateMap.get(host.getId());
+ return !isInMaintenanceMode(host) && !isDisabled(host) && haState != null
+ && Hypervisor.HypervisorType.Simulator.equals(host.getHypervisorType());
+ }
+
+ @Override
+ public boolean isHealthy(final Host host) throws HACheckerException {
+ final SimulatorHAState haState = hostHAStateMap.get(host.getId());
+ return haState != null && haState.isHealthy();
+ }
+
+ @Override
+ public boolean hasActivity(final Host host, final DateTime afterThis) throws HACheckerException {
+ final SimulatorHAState haState = hostHAStateMap.get(host.getId());
+ return haState != null && haState.hasActivity();
+ }
+
+ @Override
+ public boolean recover(final Host host) throws HARecoveryException {
+ final SimulatorHAState haState = hostHAStateMap.get(host.getId());
+ return haState != null && haState.canRecover();
+ }
+
+ @Override
+ public boolean fence(final Host host) throws HAFenceException {
+ final SimulatorHAState haState = hostHAStateMap.get(host.getId());
+ return haState != null && haState.canFenced();
+ }
+
+ @Override
+ public Object getConfigValue(final HAProvider.HAProviderConfig name, final Host host) {
+ switch (name) {
+ case HealthCheckTimeout:
+ return 5L;
+ case ActivityCheckTimeout:
+ return 5L;
+ case RecoveryTimeout:
+ return 5L;
+ case FenceTimeout:
+ return 5L;
+ case MaxActivityCheckInterval:
+ return 1L;
+ case MaxActivityChecks:
+ return 3L;
+ case ActivityCheckFailureRatio:
+ final SimulatorHAState haState = hostHAStateMap.get(host.getId());
+ return (haState != null && haState.hasActivity()) ? 1.0 : 0.0;
+ case MaxDegradedWaitTimeout:
+ return 1L;
+ case MaxRecoveryAttempts:
+ return 2L;
+ case RecoveryWaitTimeout:
+ return 1L;
+ default:
+ throw new InvalidParameterException("Unknown HAProviderConfig " + name.toString());
+ }
+ }
+
+ private boolean addStateTransition(final HAConfig vo, final boolean status,
+ final HAConfig.HAState oldState, final HAConfig.HAState newState, final HAConfig.Event event) {
+ if (vo.getResourceType() != HAResource.ResourceType.Host) {
+ return false;
+ }
+ final SimulatorHAState haState = hostHAStateMap.get(vo.getResourceId());
+ if (haState == null || !status) {
+ return false;
+ }
+ final HAResourceCounter counter = haManager.getHACounter(vo.getResourceId(), vo.getResourceType());
+ return haState.addStateTransition(newState, oldState, event, counter);
+ }
+
+ @Override
+ public boolean preStateTransitionEvent(final HAConfig.HAState oldState, final HAConfig.Event event,
+ final HAConfig.HAState newState, final HAConfig vo, final boolean status, final Object opaque) {
+ return addStateTransition(vo, status, oldState, newState, event);
+ }
+
+ @Override
+ public boolean postStateTransitionEvent(final StateMachine2.Transition<HAConfig.HAState, HAConfig.Event> transition,
+ final HAConfig vo, final boolean status, final Object opaque) {
+ return addStateTransition(vo, status, transition.getCurrentState(), transition.getToState(), transition.getEvent());
+ }
+}
\ No newline at end of file
diff --git a/plugins/hypervisors/simulator/src/org/apache/cloudstack/ha/SimulatorHAState.java b/plugins/hypervisors/simulator/src/org/apache/cloudstack/ha/SimulatorHAState.java
new file mode 100644
index 00000000000..f47ed2f11a2
--- /dev/null
+++ b/plugins/hypervisors/simulator/src/org/apache/cloudstack/ha/SimulatorHAState.java
@@ -0,0 +1,89 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ha;
+
+import com.cloud.api.response.SimulatorHAStateResponse;
+import com.google.common.collect.EvictingQueue;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Queue;
+
+public final class SimulatorHAState {
+ private boolean healthy;
+ private boolean activity;
+ private boolean recover;
+ private boolean fence;
+ private Queue<SimulatorHAStateResponse> stateTransitions = EvictingQueue.create(100);
+
+ public SimulatorHAState(boolean healthy, boolean activity, boolean recover, boolean fence) {
+ this.healthy = healthy;
+ this.activity = activity;
+ this.recover = recover;
+ this.fence = fence;
+ }
+
+ public boolean isHealthy() {
+ return healthy;
+ }
+
+ public void setHealthy(boolean healthy) {
+ this.healthy = healthy;
+ }
+
+ public boolean hasActivity() {
+ return activity;
+ }
+
+ public void setActivity(boolean activity) {
+ this.activity = activity;
+ }
+
+ public boolean canRecover() {
+ return recover;
+ }
+
+ public void setRecover(boolean recover) {
+ this.recover = recover;
+ }
+
+ public boolean canFenced() {
+ return fence;
+ }
+
+ public void setFence(boolean fence) {
+ this.fence = fence;
+ }
+
+ public boolean addStateTransition(final HAConfig.HAState newHaState, final HAConfig.HAState oldHaState, final HAConfig.Event event, final HAResourceCounter counter) {
+ final SimulatorHAStateResponse stateResponse = new SimulatorHAStateResponse();
+ stateResponse.setHaState(newHaState);
+ stateResponse.setPreviousHaState(oldHaState);
+ stateResponse.setHaEvent(event);
+ if (counter != null) {
+ stateResponse.setActivityCounter(counter.getActivityCheckCounter());
+ stateResponse.setRecoveryCounter(counter.getRecoveryCounter());
+ }
+ stateResponse.setObjectName("hastatetransition");
+ return stateTransitions.add(stateResponse);
+ }
+
+ public List<SimulatorHAStateResponse> listRecentStateTransitions() {
+ return new ArrayList<>(stateTransitions);
+ }
+}
diff --git a/plugins/hypervisors/ucs/pom.xml b/plugins/hypervisors/ucs/pom.xml
index 4926bff6058..8f6e148d7e1 100755
--- a/plugins/hypervisors/ucs/pom.xml
+++ b/plugins/hypervisors/ucs/pom.xml
@@ -15,7 +15,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>cloud-plugin-hypervisor-ucs</artifactId>
diff --git a/plugins/hypervisors/vmware/pom.xml b/plugins/hypervisors/vmware/pom.xml
index 42f14d7d5de..0344ae6862f 100644
--- a/plugins/hypervisors/vmware/pom.xml
+++ b/plugins/hypervisors/vmware/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
index 64ca4067cee..d8076fd5d68 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
@@ -94,6 +94,7 @@
import com.cloud.utils.db.DB;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
+import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.NicProfile;
import com.cloud.vm.NicVO;
import com.cloud.vm.SecondaryStorageVmVO;
@@ -101,6 +102,7 @@
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.VmDetailConstants;
+import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.VMInstanceDao;
@@ -128,6 +130,8 @@
@Inject
private NicDao _nicDao;
@Inject
+ private DomainRouterDao _domainRouterDao;
+ @Inject
private PhysicalNetworkTrafficTypeDao _physicalNetworkTrafficTypeDao;
@Inject
private VMInstanceDao _vmDao;
@@ -216,6 +220,10 @@ public VirtualMachineTO implement(VirtualMachineProfile vm) {
}
}
+ if (vm.getType() == VirtualMachine.Type.NetScalerVm) {
+ details.put(VmDetailConstants.ROOT_DISK_CONTROLLER, "scsi");
+ }
+
List<NicProfile> nicProfiles = vm.getNics();
for (NicProfile nicProfile : nicProfiles) {
@@ -292,6 +300,19 @@ public VirtualMachineTO implement(VirtualMachineProfile vm) {
}
to.setNics(expandedNics);
+
+ VirtualMachine router = vm.getVirtualMachine();
+ DomainRouterVO routerVO = _domainRouterDao.findById(router.getId());
+ if (routerVO != null && routerVO.getIsRedundantRouter()) {
+ Long peerRouterId = _nicDao.getPeerRouterId(publicNicProfile.getMacAddress(), router.getId());
+ DomainRouterVO peerRouterVO = null;
+ if (peerRouterId != null) {
+ peerRouterVO = _domainRouterDao.findById(peerRouterId);
+ if (peerRouterVO != null) {
+ details.put("PeerRouterInstanceName", peerRouterVO.getInstanceName());
+ }
+ }
+ }
}
StringBuffer sbMacSequence = new StringBuffer();
@@ -510,6 +531,7 @@ public int compare(NicTO arg0, NicTO arg1) {
// FIXME: Fix long checkPointId2 = _checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), workerName2));
cmd.setContextParam("worker2", workerName2);
cmd.setContextParam("checkpoint2", String.valueOf(checkPointId2));
+ cmd.setContextParam("searchexludefolders", _vmwareMgr.s_vmwareSearchExcludeFolder.value());
}
return new Pair<Boolean, Long>(Boolean.TRUE, cmdTarget.first().getId());
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/CleanupFullyClonedTemplatesTask.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/CleanupFullyClonedTemplatesTask.java
new file mode 100644
index 00000000000..41bbcb027ae
--- /dev/null
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/CleanupFullyClonedTemplatesTask.java
@@ -0,0 +1,158 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.hypervisor.vmware.manager;
+
+import com.cloud.api.query.dao.TemplateJoinDao;
+import com.cloud.api.query.vo.TemplateJoinVO;
+import com.cloud.hypervisor.Hypervisor;
+import com.cloud.hypervisor.HypervisorGuru;
+import com.cloud.storage.VMTemplateStoragePoolVO;
+import com.cloud.storage.dao.VMTemplatePoolDao;
+import com.cloud.template.TemplateManager;
+import com.cloud.template.VirtualMachineTemplate;
+import com.cloud.vm.UserVmCloneSettingVO;
+import com.cloud.vm.VMInstanceVO;
+import com.cloud.vm.dao.UserVmCloneSettingDao;
+import com.cloud.vm.dao.VMInstanceDao;
+import org.apache.cloudstack.engine.orchestration.VolumeOrchestrator;
+import org.apache.cloudstack.managed.context.ManagedContextRunnable;
+import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
+import org.apache.log4j.Logger;
+
+import java.util.List;
+
+/**
+ * This Task marks templates that are only used as fully cloned templates and have been deleted from CloudStack for removal from primary stores.
+ */
+public class CleanupFullyClonedTemplatesTask extends ManagedContextRunnable {
+
+ private static final Logger s_logger = Logger.getLogger(CleanupFullyClonedTemplatesTask.class);
+
+ private PrimaryDataStoreDao primaryStorageDao;
+ private VMTemplatePoolDao templateDataStoreDao;
+ private TemplateJoinDao templateDao;
+ private VMInstanceDao vmInstanceDao;
+ private UserVmCloneSettingDao cloneSettingDao;
+ private TemplateManager templateManager;
+
+ private Thread mine;
+
+ CleanupFullyClonedTemplatesTask(PrimaryDataStoreDao primaryStorageDao,
+ VMTemplatePoolDao templateDataStoreDao,
+ TemplateJoinDao templateDao,
+ VMInstanceDao vmInstanceDao,
+ UserVmCloneSettingDao cloneSettingDao,
+ TemplateManager templateManager) {
+ this.primaryStorageDao = primaryStorageDao;
+ this.templateDataStoreDao = templateDataStoreDao;
+ this.templateDao = templateDao;
+ this.vmInstanceDao = vmInstanceDao;
+ this.cloneSettingDao = cloneSettingDao;
+ this.templateManager = templateManager;
+ if(s_logger.isDebugEnabled()) {
+ s_logger.debug("new task created: " + this);
+ }
+ }
+
+ @Override
+ public void runInContext() {
+ mine = Thread.currentThread();
+ s_logger.info("running job to mark fully cloned templates for gc in thread " + mine.getName());
+
+ if (HypervisorGuru.VmwareFullClone.value()) { // only run if full cloning is being used (might need to be more fine grained)
+ try {
+ queryAllPools();
+ } catch (Throwable t) {
+ s_logger.error("error during job to mark fully cloned templates for gc in thread " + mine.getName());
+ if(s_logger.isDebugEnabled()) {
+ s_logger.debug("running job to mark fully cloned templates for gc in thread " + mine.getName(),t);
+ }
+ }
+ }
+ }
+
+ private void queryAllPools() {
+ List<StoragePoolVO> storagePools = primaryStorageDao.listAll();
+ for (StoragePoolVO pool : storagePools) {
+ long zoneId = pool.getDataCenterId();
+ queryPoolForTemplates(pool, zoneId);
+ }
+ }
+
+ private void queryPoolForTemplates(StoragePoolVO pool, long zoneId) {
+ // we don't need those specific to other hypervisor types
+ if (pool.getHypervisor() == null || Hypervisor.HypervisorType.VMware.equals(pool.getHypervisor())) {
+ if(s_logger.isDebugEnabled()) {
+ s_logger.debug(mine.getName() + " is marking fully cloned templates in pool " + pool.getName());
+ }
+ List<VMTemplateStoragePoolVO> templatePrimaryDataStoreVOS = templateDataStoreDao.listByPoolId(pool.getId());
+ for (VMTemplateStoragePoolVO templateMapping : templatePrimaryDataStoreVOS) {
+ if (canRemoveTemplateFromZone(zoneId, templateMapping)) {
+ templateManager.evictTemplateFromStoragePool(templateMapping);
+ }
+ }
+ } else {
+ if(s_logger.isDebugEnabled()) {
+ s_logger.debug(mine.getName() + " is ignoring pool " + pool.getName() + " id == " + pool.getId());
+ }
+ }
+ }
+
+ private boolean canRemoveTemplateFromZone(long zoneId, VMTemplateStoragePoolVO templateMapping) {
+ if (!templateMapping.getMarkedForGC()) {
+ if(s_logger.isDebugEnabled()) {
+ s_logger.debug(mine.getName() + " is checking template with id " + templateMapping.getTemplateId() + " for deletion from pool with id " + templateMapping.getPoolId());
+ }
+
+ TemplateJoinVO templateJoinVO = templateDao.findByIdIncludingRemoved(templateMapping.getTemplateId());
+ // check if these are deleted (not removed is null)
+ if (VirtualMachineTemplate.State.Inactive.equals(templateJoinVO.getTemplateState())) { // meaning it is removed!
+ // see if we can find vms using it with user_vm_clone_setting != full
+ return markedForGc(templateMapping, zoneId);
+ }
+ }
+ return false;
+ }
+
+ private boolean markedForGc(VMTemplateStoragePoolVO templateMapping, long zoneId) {
+ boolean used = false;
+ List<VMInstanceVO> vms = vmInstanceDao.listNonExpungedByZoneAndTemplate(zoneId, templateMapping.getTemplateId());
+ for (VMInstanceVO vm : vms) {
+ try {
+ UserVmCloneSettingVO cloneSetting = cloneSettingDao.findByVmId(vm.getId());
+ // VolumeOrchestrator or UserVmManagerImpl depending on version
+ if (VolumeOrchestrator.UserVmCloneType.linked.equals(VolumeOrchestrator.UserVmCloneType.valueOf(cloneSetting.getCloneType()))) {
+ used = true;
+ break;
+ }
+ } catch (Exception e) {
+ s_logger.error("failed to retrieve vm clone setting for vm " + vm.toString());
+ if(s_logger.isDebugEnabled()) {
+ s_logger.debug("failed to retrieve vm clone setting for vm " + vm.toString(), e);
+ }
+ }
+ }
+ if (!used) {
+ s_logger.info(mine.getName() + " is marking template with id " + templateMapping.getTemplateId() + " for gc in pool with id " + templateMapping.getPoolId());
+ // else
+ // mark it for removal from primary store
+ templateMapping.setMarkedForGC(true);
+ }
+ return !used;
+ }
+}
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java
index 12c48fee026..4a4d2ea7a53 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java
@@ -16,28 +16,32 @@
// under the License.
package com.cloud.hypervisor.vmware.manager;
-import java.io.File;
-import java.util.List;
-import java.util.Map;
-
-import com.vmware.vim25.ManagedObjectReference;
-
-import org.apache.cloudstack.framework.config.ConfigKey;
-
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.hypervisor.vmware.mo.HostMO;
import com.cloud.hypervisor.vmware.util.VmwareContext;
import com.cloud.utils.Pair;
+import com.vmware.vim25.ManagedObjectReference;
+import org.apache.cloudstack.framework.config.ConfigKey;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
public interface VmwareManager {
public final String CONTEXT_STOCK_NAME = "vmwareMgr";
public static final ConfigKey<Long> s_vmwareNicHotplugWaitTimeout = new ConfigKey<Long>("Advanced", Long.class, "vmware.nic.hotplug.wait.timeout", "15000",
- "Wait timeout (milli seconds) for hot plugged NIC of VM to be detected by guest OS.", false, ConfigKey.Scope.Global);
+ "Wait timeout (milli seconds) for hot plugged NIC of VM to be detected by guest OS.", false, ConfigKey.Scope.Global);
+
+ public static final ConfigKey<Long> templateCleanupInterval = new ConfigKey<Long>("Advanced", Long.class, "vmware.full.clone.template.cleanup.period", "0",
+ "period (in minutes) between the start of template cleanup jobs for vmware full cloned templates.", false, ConfigKey.Scope.Global);
public static final ConfigKey<Boolean> s_vmwareCleanOldWorderVMs = new ConfigKey<Boolean>("Advanced", Boolean.class, "vmware.clean.old.worker.vms", "false",
"If a worker vm is older then twice the 'job.expire.minutes' + 'job.cancel.threshold.minutes' , remove it.", true, ConfigKey.Scope.Global);
+ static final ConfigKey<String> s_vmwareSearchExcludeFolder = new ConfigKey<String>("Advanced", String.class, "vmware.search.exclude.folders", null,
+ "Comma seperated list of Datastore Folders to exclude from VMWare search", true, ConfigKey.Scope.Global);
+
String composeWorkerName();
String getSystemVMIsoFileNameOnDatastore();
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
index b0f87af648d..b7149ab2bf9 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
@@ -16,43 +16,6 @@
// under the License.
package com.cloud.hypervisor.vmware.manager;
-import java.io.File;
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.rmi.RemoteException;
-import java.time.Duration;
-import java.time.Instant;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.UUID;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-import javax.inject.Inject;
-import javax.naming.ConfigurationException;
-
-import org.apache.cloudstack.framework.jobs.impl.AsyncJobManagerImpl;
-import org.apache.log4j.Logger;
-
-import com.vmware.vim25.AboutInfo;
-import com.vmware.vim25.ManagedObjectReference;
-
-import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd;
-import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcsCmd;
-import org.apache.cloudstack.api.command.admin.zone.RemoveVmwareDcCmd;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
-import org.apache.cloudstack.framework.config.ConfigKey;
-import org.apache.cloudstack.framework.config.Configurable;
-import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
-import org.apache.cloudstack.utils.identity.ManagementServerNode;
-
import com.cloud.agent.AgentManager;
import com.cloud.agent.Listener;
import com.cloud.agent.api.AgentControlAnswer;
@@ -61,6 +24,7 @@
import com.cloud.agent.api.Command;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
+import com.cloud.api.query.dao.TemplateJoinDao;
import com.cloud.cluster.ClusterManager;
import com.cloud.cluster.ManagementServerHost;
import com.cloud.cluster.dao.ManagementServerHostPeerDao;
@@ -103,9 +67,9 @@
import com.cloud.hypervisor.vmware.util.VmwareHelper;
import com.cloud.network.CiscoNexusVSMDeviceVO;
import com.cloud.network.NetworkModel;
-import com.cloud.network.VmwareTrafficLabel;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.TrafficType;
+import com.cloud.network.VmwareTrafficLabel;
import com.cloud.network.dao.CiscoNexusVSMDeviceDao;
import com.cloud.org.Cluster.ClusterType;
import com.cloud.secstorage.CommandExecLogDao;
@@ -113,6 +77,9 @@
import com.cloud.storage.ImageStoreDetailsUtil;
import com.cloud.storage.JavaStorageLayer;
import com.cloud.storage.StorageLayer;
+import com.cloud.storage.StorageManager;
+import com.cloud.storage.dao.VMTemplatePoolDao;
+import com.cloud.template.TemplateManager;
import com.cloud.utils.FileUtil;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
@@ -127,14 +94,48 @@
import com.cloud.utils.script.Script;
import com.cloud.utils.ssh.SshHelper;
import com.cloud.vm.DomainRouterVO;
+import com.cloud.vm.dao.UserVmCloneSettingDao;
+import com.cloud.vm.dao.VMInstanceDao;
+import com.vmware.vim25.AboutInfo;
+import com.vmware.vim25.ManagedObjectReference;
+import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd;
+import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcsCmd;
+import org.apache.cloudstack.api.command.admin.zone.RemoveVmwareDcCmd;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.Configurable;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.framework.jobs.impl.AsyncJobManagerImpl;
+import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.cloudstack.utils.identity.ManagementServerNode;
+import org.apache.log4j.Logger;
+
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.rmi.RemoteException;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.UUID;
+import java.util.concurrent.Executors;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
public class VmwareManagerImpl extends ManagerBase implements VmwareManager, VmwareStorageMount, Listener, VmwareDatacenterService, Configurable {
private static final Logger s_logger = Logger.getLogger(VmwareManagerImpl.class);
private static final long SECONDS_PER_MINUTE = 60;
- private static final int STARTUP_DELAY = 60000; // 60 seconds
- private static final long DEFAULT_HOST_SCAN_INTERVAL = 600000; // every 10 minutes
- private long _hostScanInterval = DEFAULT_HOST_SCAN_INTERVAL;
private int _timeout;
private String _instance;
@@ -175,6 +176,18 @@
private ClusterManager _clusterMgr;
@Inject
private ImageStoreDetailsUtil imageStoreDetailsUtil;
+ @Inject
+ private PrimaryDataStoreDao primaryStorageDao;
+ @Inject
+ private VMTemplatePoolDao templateDataStoreDao;
+ @Inject
+ private TemplateJoinDao templateDao;
+ @Inject
+ private VMInstanceDao vmInstanceDao;
+ @Inject
+ private UserVmCloneSettingDao cloneSettingDao;
+ @Inject
+ private TemplateManager templateManager;
private String _mountParent;
private StorageLayer _storage;
@@ -196,15 +209,15 @@
private final String _dataDiskController = DiskControllerType.osdefault.toString();
- private final Map<String, String> _storageMounts = new HashMap<String, String>();
+ private final Map<String, String> _storageMounts = new HashMap<>();
private final Random _rand = new Random(System.currentTimeMillis());
+ private static ScheduledExecutorService templateCleanupScheduler = Executors.newScheduledThreadPool(1, new NamedThreadFactory("Vmware-FullyClonedTemplateCheck"));;
+
private final VmwareStorageManager _storageMgr;
private final GlobalLock _exclusiveOpLock = GlobalLock.getInternLock("vmware.exclusive.op");
- private final ScheduledExecutorService _hostScanScheduler = Executors.newScheduledThreadPool(1, new NamedThreadFactory("Vmware-Host-Scan"));
-
public VmwareManagerImpl() {
_storageMgr = new VmwareStorageManagerImpl(this);
}
@@ -216,7 +229,7 @@ public String getConfigComponentName() {
@Override
public ConfigKey<?>[] getConfigKeys() {
- return new ConfigKey<?>[] {s_vmwareNicHotplugWaitTimeout, s_vmwareCleanOldWorderVMs};
+ return new ConfigKey<?>[] {s_vmwareNicHotplugWaitTimeout, s_vmwareCleanOldWorderVMs, templateCleanupInterval, s_vmwareSearchExcludeFolder};
}
@Override
@@ -313,10 +326,6 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
s_logger.info("Additional VNC port allocation range is settled at " + _additionalPortRangeStart + " to " + (_additionalPortRangeStart + _additionalPortRangeSize));
- value = _configDao.getValue("vmware.host.scan.interval");
- _hostScanInterval = NumbersUtil.parseLong(value, DEFAULT_HOST_SCAN_INTERVAL);
- s_logger.info("VmwareManagerImpl config - vmware.host.scan.interval: " + _hostScanInterval);
-
((VmwareStorageManagerImpl)_storageMgr).configure(params);
_agentMgr.registerForHostEvents(this, true, true, true);
@@ -327,21 +336,20 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
@Override
public boolean start() {
- _hostScanScheduler.scheduleAtFixedRate(getHostScanTask(), STARTUP_DELAY, _hostScanInterval, TimeUnit.MILLISECONDS);
+// Do not run empty task _hostScanScheduler.scheduleAtFixedRate(getHostScanTask(), STARTUP_DELAY, _hostScanInterval, TimeUnit.MILLISECONDS);
+// but implement it first!
+ startTemplateCleanJobSchedule();
startupCleanup(_mountParent);
+
+ s_logger.info("start done");
return true;
}
@Override
public boolean stop() {
- _hostScanScheduler.shutdownNow();
- try {
- _hostScanScheduler.awaitTermination(3000, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- s_logger.debug("[ignored] interupted while stopping<:/.");
- }
-
+ s_logger.info("shutting down scheduled tasks");
+ templateCleanupScheduler.shutdown();
shutdownCleanup();
return true;
}
@@ -384,11 +392,11 @@ private void prepareHost(HostMO hostMo, String privateTrafficLabel) throws Excep
VirtualSwitchType vsType = VirtualSwitchType.getType(vSwitchType);
//The management network is probably always going to be a physical network with islation type of vlans, so assume BroadcastDomainType VLAN
if (VirtualSwitchType.StandardVirtualSwitch == vsType) {
- HypervisorHostHelper.prepareNetwork(vSwitchName, "cloud.private", hostMo, vlanId, null, null, 180000, false, BroadcastDomainType.Vlan, null);
+ HypervisorHostHelper.prepareNetwork(vSwitchName, "cloud.private", hostMo, vlanId, null, null, 180000, false, BroadcastDomainType.Vlan, null, null);
}
else {
HypervisorHostHelper.prepareNetwork(vSwitchName, "cloud.private", hostMo, vlanId, null, null, null, 180000,
- vsType, _portsPerDvPortGroup, null, false, BroadcastDomainType.Vlan, null);
+ vsType, _portsPerDvPortGroup, null, false, BroadcastDomainType.Vlan, null, null);
}
}
@@ -670,19 +678,6 @@ public File getSystemVMKeyFile() {
return keyFile;
}
- private Runnable getHostScanTask() {
- return new Runnable() {
- @Override
- public void run() {
- // TODO scan vSphere for newly added hosts.
- // we are going to both support adding host from CloudStack UI and
- // adding host via vSphere server
- //
- // will implement host scanning later
- }
- };
- }
-
@Override
public String getMountPoint(String storageUrl, Integer nfsVersion) {
String mountPoint = null;
@@ -1288,4 +1283,55 @@ public boolean hasNexusVSM(Long clusterId) {
}
}
+ private void startTemplateCleanJobSchedule() {
+ if(s_logger.isDebugEnabled()) {
+ s_logger.debug("checking to see if we should schedule a job to search for fully cloned templates to clean-up");
+ }
+ if(StorageManager.StorageCleanupEnabled.value() &&
+ StorageManager.TemplateCleanupEnabled.value() &&
+ templateCleanupInterval.value() > 0) {
+ try {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("scheduling job to search for fully cloned templates to clean-up once per " + templateCleanupInterval.value() + " minutes.");
+ }
+// futureTemplateCleanup =
+ Runnable task = getCleanupFullyClonedTemplatesTask();
+ templateCleanupScheduler.scheduleAtFixedRate(task,
+ templateCleanupInterval.value(),
+ templateCleanupInterval.value(),
+ TimeUnit.MINUTES);
+ if (s_logger.isTraceEnabled()) {
+ s_logger.trace("scheduled job to search for fully cloned templates to clean-up.");
+ }
+ } catch (RejectedExecutionException ree) {
+ s_logger.error("job to search for fully cloned templates cannot be scheduled");
+ s_logger.debug("job to search for fully cloned templates cannot be scheduled;", ree);
+ } catch (NullPointerException npe) {
+ s_logger.error("job to search for fully cloned templates is invalid");
+ s_logger.debug("job to search for fully cloned templates is invalid;", npe);
+ } catch (IllegalArgumentException iae) {
+ s_logger.error("job to search for fully cloned templates is scheduled at invalid intervals");
+ s_logger.debug("job to search for fully cloned templates is scheduled at invalid intervals;", iae);
+ } catch (Exception e) {
+ s_logger.error("job to search for fully cloned templates failed for unknown reasons");
+ s_logger.debug("job to search for fully cloned templates failed for unknown reasons;", e);
+ }
+ }
+ }
+
+ /**
+ * This task is to cleanup templates from primary storage that are otherwise not cleaned by the {@link com.cloud.storage.StorageManagerImpl.StorageGarbageCollector}.
+ * it is called at regular intervals when storage.template.cleanup.enabled == true
+ * It collect all templates that
+ * - are deleted from cloudstack
+ * - when vmware.create.full.clone == true and the entries for VMs having volumes on the primary storage in db table ?user_vm_clone_setting? reads 'full'
+ */
+ private Runnable getCleanupFullyClonedTemplatesTask() {
+ return new CleanupFullyClonedTemplatesTask(primaryStorageDao,
+ templateDataStoreDao,
+ templateDao,
+ vmInstanceDao,
+ cloneSettingDao,
+ templateManager);
+ }
}
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
index 3158ad47925..00298cedc75 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
@@ -307,6 +307,7 @@ public Answer execute(VmwareHostService hostService, BackupSnapshotCommand cmd)
String snapshotUuid = cmd.getSnapshotUuid(); // not null: Precondition.
String prevSnapshotUuid = cmd.getPrevSnapshotUuid();
String prevBackupUuid = cmd.getPrevBackupUuid();
+ String searchExcludedFolders = cmd.getContextParam("searchexludefolders");
VirtualMachineMO workerVm = null;
String workerVMName = null;
String volumePath = cmd.getVolumePath();
@@ -344,7 +345,7 @@ public Answer execute(VmwareHostService hostService, BackupSnapshotCommand cmd)
workerVm = vmMo;
// attach volume to worker VM
- String datastoreVolumePath = getVolumePathInDatastore(dsMo, volumePath + ".vmdk");
+ String datastoreVolumePath = getVolumePathInDatastore(dsMo, volumePath + ".vmdk", searchExcludedFolders);
vmMo.attachDisk(new String[] {datastoreVolumePath}, morDs);
}
}
@@ -986,6 +987,8 @@ private void exportVolumeToSecondaryStroage(VirtualMachineMO vmMo, String volume
VirtualMachineMO workerVm = null;
VirtualMachineMO vmMo = null;
String exportName = UUID.randomUUID().toString();
+ String searchExcludedFolders = cmd.getContextParam("searchexludefolders");
+
try {
ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, poolId);
@@ -1009,7 +1012,7 @@ private void exportVolumeToSecondaryStroage(VirtualMachineMO vmMo, String volume
}
//attach volume to worker VM
- String datastoreVolumePath = getVolumePathInDatastore(dsMo, volumePath + ".vmdk");
+ String datastoreVolumePath = getVolumePathInDatastore(dsMo, volumePath + ".vmdk", searchExcludedFolders);
workerVm.attachDisk(new String[] {datastoreVolumePath}, morDs);
vmMo = workerVm;
}
@@ -1030,8 +1033,8 @@ private void exportVolumeToSecondaryStroage(VirtualMachineMO vmMo, String volume
}
}
- private String getVolumePathInDatastore(DatastoreMO dsMo, String volumeFileName) throws Exception {
- String datastoreVolumePath = dsMo.searchFileInSubFolders(volumeFileName, true);
+ private String getVolumePathInDatastore(DatastoreMO dsMo, String volumeFileName, String searchExcludeFolders) throws Exception {
+ String datastoreVolumePath = dsMo.searchFileInSubFolders(volumeFileName, true, searchExcludeFolders);
if (datastoreVolumePath == null) {
throw new CloudRuntimeException("Unable to find file " + volumeFileName + " in datastore " + dsMo.getName());
}
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
index 5c873099fd6..9d32f3424de 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
@@ -46,6 +46,7 @@
import org.apache.log4j.Logger;
import org.apache.log4j.NDC;
+import org.apache.commons.lang.StringUtils;
import com.google.gson.Gson;
import com.vmware.vim25.AboutInfo;
@@ -139,6 +140,8 @@
import com.cloud.agent.api.GetStorageStatsCommand;
import com.cloud.agent.api.GetVmDiskStatsAnswer;
import com.cloud.agent.api.GetVmDiskStatsCommand;
+import com.cloud.agent.api.GetVmNetworkStatsAnswer;
+import com.cloud.agent.api.GetVmNetworkStatsCommand;
import com.cloud.agent.api.GetVmStatsAnswer;
import com.cloud.agent.api.GetVmStatsCommand;
import com.cloud.agent.api.GetVncPortAnswer;
@@ -407,6 +410,8 @@ public Answer executeRequest(Command cmd) {
answer = execute((GetHostStatsCommand)cmd);
} else if (clz == GetVmStatsCommand.class) {
answer = execute((GetVmStatsCommand)cmd);
+ } else if (clz == GetVmNetworkStatsCommand.class) {
+ answer = execute((GetVmNetworkStatsCommand) cmd);
} else if (clz == GetVmDiskStatsCommand.class) {
answer = execute((GetVmDiskStatsCommand)cmd);
} else if (clz == CheckHealthCommand.class) {
@@ -640,7 +645,7 @@ private void registerVm(String vmName, DatastoreMO dsMo) throws Exception{
ManagedObjectReference vmFolderMor = dataCenterMo.getVmFolder();
//2nd param
- String vmxFilePath = dsMo.searchFileInSubFolders(vmName + ".vmx", false);
+ String vmxFilePath = dsMo.searchFileInSubFolders(vmName + ".vmx", false, VmwareManager.s_vmwareSearchExcludeFolder.value());
// 5th param
ManagedObjectReference morPool = hyperHost.getHyperHostOwnerResourcePool();
@@ -1080,18 +1085,15 @@ private PlugNicAnswer execute(PlugNicCommand cmd) {
ManagedObjectReference dvsMor = dataCenterMo.getDvSwitchMor(networkInfo.first());
dvSwitchUuid = dataCenterMo.getDvSwitchUuid(dvsMor);
s_logger.info("Preparing NIC device on dvSwitch : " + dvSwitchUuid);
- nic =
- VmwareHelper.prepareDvNicDevice(vmMo, networkInfo.first(), nicDeviceType, networkInfo.second(), dvSwitchUuid, nicTo.getMac(), deviceNumber,
- deviceNumber + 1, true, true);
+ nic = VmwareHelper.prepareDvNicDevice(vmMo, networkInfo.first(), nicDeviceType, networkInfo.second(), dvSwitchUuid,
+ nicTo.getMac(), deviceNumber + 1, true, true);
} else {
s_logger.info("Preparing NIC device on network " + networkInfo.second());
- nic =
- VmwareHelper.prepareNicDevice(vmMo, networkInfo.first(), nicDeviceType, networkInfo.second(), nicTo.getMac(), deviceNumber, deviceNumber + 1, true,
- true);
+ nic = VmwareHelper.prepareNicDevice(vmMo, networkInfo.first(), nicDeviceType, networkInfo.second(),
+ nicTo.getMac(), deviceNumber + 1, true, true);
}
VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec();
- //VirtualDeviceConfigSpec[] deviceConfigSpecArray = new VirtualDeviceConfigSpec[1];
VirtualDeviceConfigSpec deviceConfigSpec = new VirtualDeviceConfigSpec();
deviceConfigSpec.setDevice(nic);
deviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
@@ -1176,11 +1178,11 @@ private void plugPublicNic(VirtualMachineMO vmMo, final String vlanId, final Str
if (VirtualSwitchType.StandardVirtualSwitch == vSwitchType) {
networkInfo = HypervisorHostHelper.prepareNetwork(_publicTrafficInfo.getVirtualSwitchName(),
"cloud.public", vmMo.getRunningHost(), vlanId, null, null,
- _opsTimeout, true, BroadcastDomainType.Vlan, null);
+ _opsTimeout, true, BroadcastDomainType.Vlan, null, null);
} else {
networkInfo =
HypervisorHostHelper.prepareNetwork(_publicTrafficInfo.getVirtualSwitchName(), "cloud.public", vmMo.getRunningHost(), vlanId, null, null, null,
- _opsTimeout, vSwitchType, _portsPerDvPortGroup, null, false, BroadcastDomainType.Vlan, _vsmCredentials);
+ _opsTimeout, vSwitchType, _portsPerDvPortGroup, null, false, BroadcastDomainType.Vlan, _vsmCredentials, null);
}
int nicIndex = allocPublicNicIndex(vmMo);
@@ -1513,7 +1515,7 @@ private void ensureScsiDiskControllers(VirtualMachineMO vmMo, String scsiDiskCon
} else if (DiskControllerType.getType(scsiDiskController) == DiskControllerType.buslogic) {
vmMo.ensureBusLogicDeviceControllers(requiredNumScsiControllers, availableBusNum);
} else if (DiskControllerType.getType(scsiDiskController) == DiskControllerType.lsilogic) {
- vmMo.ensureScsiDeviceControllers(requiredNumScsiControllers, availableBusNum);
+ vmMo.ensureLsiLogicDeviceControllers(requiredNumScsiControllers, availableBusNum);
}
}
@@ -1678,7 +1680,7 @@ protected StartAnswer execute(StartCommand cmd) {
assert (vmSpec.getMinSpeed() != null) && (rootDiskDataStoreDetails != null);
boolean vmFolderExists = rootDiskDataStoreDetails.second().folderExists(String.format("[%s]", rootDiskDataStoreDetails.second().getName()), vmNameOnVcenter);
- String vmxFileFullPath = dsRootVolumeIsOn.searchFileInSubFolders(vmNameOnVcenter + ".vmx", false);
+ String vmxFileFullPath = dsRootVolumeIsOn.searchFileInSubFolders(vmNameOnVcenter + ".vmx", false, VmwareManager.s_vmwareSearchExcludeFolder.value());
if (vmFolderExists && vmxFileFullPath != null) { // VM can be registered only if .vmx is present.
registerVm(vmNameOnVcenter, dsRootVolumeIsOn);
vmMo = hyperHost.findVmOnHyperHost(vmInternalCSName);
@@ -1749,7 +1751,6 @@ protected StartAnswer execute(StartCommand cmd) {
int i = 0;
int ideUnitNumber = 0;
int scsiUnitNumber = 0;
- int nicUnitNumber = 0;
int ideControllerKey = vmMo.getIDEDeviceControllerKey();
int scsiControllerKey = vmMo.getGenericScsiDeviceControllerKeyNoException();
int controllerKey;
@@ -1955,6 +1956,40 @@ protected StartAnswer execute(StartCommand cmd) {
VirtualDevice nic;
int nicMask = 0;
int nicCount = 0;
+
+ if (vmSpec.getType() == VirtualMachine.Type.DomainRouter) {
+ int extraPublicNics = mgr.getRouterExtraPublicNics();
+ if (extraPublicNics > 0 && vmSpec.getDetails().containsKey("PeerRouterInstanceName")) {
+ //Set identical MAC address for RvR on extra public interfaces
+ String peerRouterInstanceName = vmSpec.getDetails().get("PeerRouterInstanceName");
+
+ VirtualMachineMO peerVmMo = hyperHost.findVmOnHyperHost(peerRouterInstanceName);
+ if (peerVmMo == null) {
+ peerVmMo = hyperHost.findVmOnPeerHyperHost(peerRouterInstanceName);
+ }
+
+ if (peerVmMo != null) {
+ String oldMacSequence = generateMacSequence(nics);
+
+ for (int nicIndex = nics.length - extraPublicNics; nicIndex < nics.length; nicIndex++) {
+ VirtualDevice nicDevice = peerVmMo.getNicDeviceByIndex(nics[nicIndex].getDeviceId());
+ if (nicDevice != null) {
+ String mac = ((VirtualEthernetCard)nicDevice).getMacAddress();
+ if (mac != null) {
+ s_logger.info("Use same MAC as previous RvR, the MAC is " + mac + " for extra NIC with device id: " + nics[nicIndex].getDeviceId());
+ nics[nicIndex].setMac(mac);
+ }
+ }
+ }
+
+ if (!StringUtils.isBlank(vmSpec.getBootArgs())) {
+ String newMacSequence = generateMacSequence(nics);
+ vmSpec.setBootArgs(replaceNicsMacSequenceInBootArgs(oldMacSequence, newMacSequence, vmSpec));
+ }
+ }
+ }
+ }
+
VirtualEthernetCardType nicDeviceType = VirtualEthernetCardType.valueOf(vmSpec.getDetails().get(VmDetailConstants.NIC_ADAPTER));
if (s_logger.isDebugEnabled())
s_logger.debug("VM " + vmInternalCSName + " will be started with NIC device type: " + nicDeviceType);
@@ -1977,21 +2012,21 @@ protected StartAnswer execute(StartCommand cmd) {
ManagedObjectReference dvsMor = dataCenterMo.getDvSwitchMor(networkInfo.first());
dvSwitchUuid = dataCenterMo.getDvSwitchUuid(dvsMor);
s_logger.info("Preparing NIC device on dvSwitch : " + dvSwitchUuid);
- nic =
- VmwareHelper.prepareDvNicDevice(vmMo, networkInfo.first(), nicDeviceType, networkInfo.second(), dvSwitchUuid, nicTo.getMac(), nicUnitNumber++,
- i + 1, true, true);
+ nic = VmwareHelper.prepareDvNicDevice(vmMo, networkInfo.first(), nicDeviceType, networkInfo.second(), dvSwitchUuid,
+ nicTo.getMac(), i + 1, true, true);
if (nicTo.getUuid() != null) {
nicUuidToDvSwitchUuid.put(nicTo.getUuid(), dvSwitchUuid);
}
} else {
s_logger.info("Preparing NIC device on network " + networkInfo.second());
- nic =
- VmwareHelper.prepareNicDevice(vmMo, networkInfo.first(), nicDeviceType, networkInfo.second(), nicTo.getMac(), nicUnitNumber++, i + 1, true, true);
+ nic = VmwareHelper.prepareNicDevice(vmMo, networkInfo.first(), nicDeviceType, networkInfo.second(),
+ nicTo.getMac(), i + 1, true, true);
}
}
else{
//if NSX API VERSION >= 4.2, connect to br-int (nsx.network), do not create portgroup else previous behaviour
- nic = VmwareHelper.prepareNicOpaque(vmMo, nicDeviceType, networkInfo.second(), nicTo.getMac(), nicUnitNumber++, i + 1, true, true);
+ nic = VmwareHelper.prepareNicOpaque(vmMo, nicDeviceType, networkInfo.second(),
+ nicTo.getMac(), i + 1, true, true);
}
deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
@@ -2022,6 +2057,16 @@ protected StartAnswer execute(StartCommand cmd) {
configNvpExtraOption(extraOptions, vmSpec, nicUuidToDvSwitchUuid);
configCustomExtraOption(extraOptions, vmSpec);
+ // config for NCC
+ VirtualMachine.Type vmType = cmd.getVirtualMachine().getType();
+ if (vmType.equals(VirtualMachine.Type.NetScalerVm)) {
+ NicTO mgmtNic = vmSpec.getNics()[0];
+ OptionValue option = new OptionValue();
+ option.setKey("machine.id");
+ option.setValue("ip=" + mgmtNic.getIp() + "&netmask=" + mgmtNic.getNetmask() + "&gateway=" + mgmtNic.getGateway());
+ extraOptions.add(option);
+ }
+
// config VNC
String keyboardLayout = null;
if (vmSpec.getDetails() != null)
@@ -2152,6 +2197,36 @@ private void resizeRootDisk(VirtualMachineMO vmMo, DiskTO rootDiskTO, VmwareHype
}
+ /**
+ * Generate the mac sequence from the nics.
+ */
+ protected String generateMacSequence(NicTO[] nics) {
+ if (nics.length == 0) {
+ return "";
+ }
+
+ StringBuffer sbMacSequence = new StringBuffer();
+ for (NicTO nicTo : sortNicsByDeviceId(nics)) {
+ sbMacSequence.append(nicTo.getMac()).append("|");
+ }
+ if (!sbMacSequence.toString().isEmpty()) {
+ sbMacSequence.deleteCharAt(sbMacSequence.length() - 1); //Remove extra '|' char appended at the end
+ }
+
+ return sbMacSequence.toString();
+ }
+
+ /**
+ * Update boot args with the new nic mac addresses.
+ */
+ protected String replaceNicsMacSequenceInBootArgs(String oldMacSequence, String newMacSequence, VirtualMachineTO vmSpec) {
+ String bootArgs = vmSpec.getBootArgs();
+ if (!StringUtils.isBlank(bootArgs) && !StringUtils.isBlank(oldMacSequence) && !StringUtils.isBlank(newMacSequence)) {
+ return bootArgs.replace(oldMacSequence, newMacSequence);
+ }
+ return "";
+ }
+
/**
* Sets video card memory to the one provided in detail svga.vramSize (if provided) on {@code vmConfigSpec}.
* 64MB was always set before.
@@ -2281,7 +2356,7 @@ int getReservedCpuMHZ(VirtualMachineTO vmSpec) {
DatastoreFile file = new DatastoreFile(disks[i]);
if (!isManaged && file.getDir() != null && file.getDir().isEmpty()) {
s_logger.info("Perform run-time datastore folder upgrade. sync " + disks[i] + " to VM folder");
- disks[i] = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, file.getFileBaseName());
+ disks[i] = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, file.getFileBaseName(), VmwareManager.s_vmwareSearchExcludeFolder.value());
}
}
return disks;
@@ -2291,13 +2366,13 @@ int getReservedCpuMHZ(VirtualMachineTO vmSpec) {
if (isManaged) {
if (volumeTO.getVolumeType() == Volume.Type.ROOT) {
- datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, volumeTO.getName());
+ datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, volumeTO.getName(), VmwareManager.s_vmwareSearchExcludeFolder.value());
}
else {
datastoreDiskPath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk");
}
} else {
- datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, volumeTO.getPath());
+ datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, volumeTO.getPath(), VmwareManager.s_vmwareSearchExcludeFolder.value());
}
if (!dsMo.fileExists(datastoreDiskPath)) {
@@ -2723,7 +2798,7 @@ else if (file.getType().equals("config"))
vmFolder = new DatastoreFile(fileInDatastore.getDatastoreName(), fileInDatastore.getDir());
DatastoreMO dsMo = new DatastoreMO(dcMo.getContext(), dcMo.findDatastore(fileInDatastore.getDatastoreName()));
s_logger.debug("Deleting file: " + file.getName());
- dsMo.deleteFile(file.getName(), dcMo.getMor(), true);
+ dsMo.deleteFile(file.getName(), dcMo.getMor(), true, VmwareManager.s_vmwareSearchExcludeFolder.value());
}
// Delete files that are present in the VM folder - this will take care of the VM disks as well.
DatastoreMO vmFolderDsMo = new DatastoreMO(dcMo.getContext(), dcMo.findDatastore(vmFolder.getDatastoreName()));
@@ -2732,7 +2807,7 @@ else if (file.getType().equals("config"))
for (String file : files) {
String vmDiskFileFullPath = String.format("%s/%s", vmFolder.getPath(), file);
s_logger.debug("Deleting file: " + vmDiskFileFullPath);
- vmFolderDsMo.deleteFile(vmDiskFileFullPath, dcMo.getMor(), true);
+ vmFolderDsMo.deleteFile(vmDiskFileFullPath, dcMo.getMor(), true, VmwareManager.s_vmwareSearchExcludeFolder.value());
}
}
// Delete VM folder
@@ -2957,7 +3032,7 @@ private String getVlanInfo(NicTO nicTo, String defaultVlan) {
if (VirtualSwitchType.StandardVirtualSwitch == switchType) {
networkInfo = HypervisorHostHelper.prepareNetwork(switchName, namePrefix, hostMo,
getVlanInfo(nicTo, vlanToken), nicTo.getNetworkRateMbps(), nicTo.getNetworkRateMulticastMbps(),
- _opsTimeout, !namePrefix.startsWith("cloud.private"), nicTo.getBroadcastType(), nicTo.getUuid());
+ _opsTimeout, true, nicTo.getBroadcastType(), nicTo.getUuid(), nicTo.getDetails());
}
else {
String vlanId = getVlanInfo(nicTo, vlanToken);
@@ -2972,7 +3047,7 @@ private String getVlanInfo(NicTO nicTo, String defaultVlan) {
}
networkInfo = HypervisorHostHelper.prepareNetwork(switchName, namePrefix, hostMo, vlanId, svlanId,
nicTo.getNetworkRateMbps(), nicTo.getNetworkRateMulticastMbps(), _opsTimeout, switchType,
- _portsPerDvPortGroup, nicTo.getGateway(), configureVServiceInNexus, nicTo.getBroadcastType(), _vsmCredentials);
+ _portsPerDvPortGroup, nicTo.getGateway(), configureVServiceInNexus, nicTo.getBroadcastType(), _vsmCredentials, nicTo.getDetails());
}
return networkInfo;
@@ -3196,6 +3271,10 @@ protected Answer execute(GetVmDiskStatsCommand cmd) {
return new GetVmDiskStatsAnswer(cmd, null, null, null);
}
+ protected Answer execute(GetVmNetworkStatsCommand cmd) {
+ return new GetVmNetworkStatsAnswer(cmd, null, null, null);
+ }
+
protected Answer execute(CheckHealthCommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource CheckHealthCommand: " + _gson.toJson(cmd));
diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageLayoutHelper.java b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageLayoutHelper.java
index 4096333c493..fc79a4b0faf 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageLayoutHelper.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageLayoutHelper.java
@@ -67,6 +67,11 @@
}
public static String findVolumeDatastoreFullPath(DatastoreMO dsMo, String vmName, String vmdkFileName) throws Exception {
+ return findVolumeDatastoreFullPath(dsMo, vmName, vmdkFileName, null);
+ }
+
+ public static String findVolumeDatastoreFullPath(DatastoreMO dsMo, String vmName, String vmdkFileName, String excludeFolders) throws Exception {
+
if (vmName != null) {
String path = getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, vmdkFileName);
if (!dsMo.fileExists(path)) {
@@ -80,7 +85,7 @@ public static String findVolumeDatastoreFullPath(DatastoreMO dsMo, String vmName
String path = getLegacyDatastorePathFromVmdkFileName(dsMo, vmdkFileName);
if (!dsMo.fileExists(path)) {
// Datastore file movement is not atomic operations, we need to sync and repair
- path = dsMo.searchFileInSubFolders(vmdkFileName, false);
+ path = dsMo.searchFileInSubFolders(vmdkFileName, false, excludeFolders);
// to save one call to vCenter, we won't check file existence for this round, so the caller
// may still fail with exception, but if that's case, we will let it fail anyway
@@ -90,6 +95,10 @@ public static String findVolumeDatastoreFullPath(DatastoreMO dsMo, String vmName
}
public static String syncVolumeToVmDefaultFolder(DatacenterMO dcMo, String vmName, DatastoreMO ds, String vmdkName) throws Exception {
+ return syncVolumeToVmDefaultFolder(dcMo, vmName, ds, vmdkName, null);
+ }
+
+ public static String syncVolumeToVmDefaultFolder(DatacenterMO dcMo, String vmName, DatastoreMO ds, String vmdkName, String excludeFolders) throws Exception {
assert (ds != null);
if (!ds.folderExists(String.format("[%s]", ds.getName()), vmName)) {
@@ -109,7 +118,7 @@ public static String syncVolumeToVmDefaultFolder(DatacenterMO dcMo, String vmNam
// be left over in its previous owner VM. We will do a fixup synchronization here by moving it to root
// again.
//
- syncVolumeToRootFolder(dcMo, ds, vmdkName, vmName);
+ syncVolumeToRootFolder(dcMo, ds, vmdkName, vmName, excludeFolders);
}
if (ds.fileExists(vmdkFullCloneModeLegacyPair[1])) {
@@ -134,7 +143,11 @@ public static String syncVolumeToVmDefaultFolder(DatacenterMO dcMo, String vmNam
}
public static void syncVolumeToRootFolder(DatacenterMO dcMo, DatastoreMO ds, String vmdkName, String vmName) throws Exception {
- String fileDsFullPath = ds.searchFileInSubFolders(vmdkName + ".vmdk", false);
+ syncVolumeToRootFolder(dcMo, ds, vmdkName, null);
+ }
+
+ public static void syncVolumeToRootFolder(DatacenterMO dcMo, DatastoreMO ds, String vmdkName, String vmName, String excludeFolders) throws Exception {
+ String fileDsFullPath = ds.searchFileInSubFolders(vmdkName + ".vmdk", false, excludeFolders);
if (fileDsFullPath == null)
return;
@@ -259,13 +272,17 @@ public static String getTemplateOnSecStorageFilePath(String secStorageMountPoint
}
public static void deleteVolumeVmdkFiles(DatastoreMO dsMo, String volumeName, DatacenterMO dcMo) throws Exception {
+ deleteVolumeVmdkFiles(dsMo, volumeName, dcMo, null);
+ }
+
+ public static void deleteVolumeVmdkFiles(DatastoreMO dsMo, String volumeName, DatacenterMO dcMo, String excludeFolders) throws Exception {
String fileName = volumeName + ".vmdk";
String fileFullPath = getLegacyDatastorePathFromVmdkFileName(dsMo, fileName);
if (!dsMo.fileExists(fileFullPath))
- fileFullPath = dsMo.searchFileInSubFolders(fileName, false);
+ fileFullPath = dsMo.searchFileInSubFolders(fileName, false, excludeFolders);
if (fileFullPath != null) {
- dsMo.deleteFile(fileFullPath, dcMo.getMor(), true);
+ dsMo.deleteFile(fileFullPath, dcMo.getMor(), true, excludeFolders);
} else {
s_logger.warn("Unable to locate VMDK file: " + fileName);
}
@@ -273,9 +290,9 @@ public static void deleteVolumeVmdkFiles(DatastoreMO dsMo, String volumeName, Da
fileName = volumeName + "-flat.vmdk";
fileFullPath = getLegacyDatastorePathFromVmdkFileName(dsMo, fileName);
if (!dsMo.fileExists(fileFullPath))
- fileFullPath = dsMo.searchFileInSubFolders(fileName, false);
+ fileFullPath = dsMo.searchFileInSubFolders(fileName, false, excludeFolders);
if (fileFullPath != null) {
- dsMo.deleteFile(fileFullPath, dcMo.getMor(), true);
+ dsMo.deleteFile(fileFullPath, dcMo.getMor(), true, excludeFolders);
} else {
s_logger.warn("Unable to locate VMDK file: " + fileName);
}
@@ -283,9 +300,9 @@ public static void deleteVolumeVmdkFiles(DatastoreMO dsMo, String volumeName, Da
fileName = volumeName + "-delta.vmdk";
fileFullPath = getLegacyDatastorePathFromVmdkFileName(dsMo, fileName);
if (!dsMo.fileExists(fileFullPath))
- fileFullPath = dsMo.searchFileInSubFolders(fileName, false);
+ fileFullPath = dsMo.searchFileInSubFolders(fileName, false, excludeFolders);
if (fileFullPath != null) {
- dsMo.deleteFile(fileFullPath, dcMo.getMor(), true);
+ dsMo.deleteFile(fileFullPath, dcMo.getMor(), true, excludeFolders);
} else {
s_logger.warn("Unable to locate VMDK file: " + fileName);
}
diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
index 802657515fd..012556eb1ca 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
@@ -450,6 +450,7 @@ public Answer cloneVolumeFromBaseTemplate(CopyCommand cmd) {
VolumeObjectTO volume = (VolumeObjectTO)destData;
DataStoreTO primaryStore = volume.getDataStore();
DataStoreTO srcStore = template.getDataStore();
+ String searchExcludedFolders = cmd.getContextParam("searchexludefolders");
try {
VmwareContext context = hostService.getServiceContext(null);
@@ -481,7 +482,7 @@ public Answer cloneVolumeFromBaseTemplate(CopyCommand cmd) {
String volumeDatastorePath = vmdkFilePair[0];
synchronized (this) {
s_logger.info("Delete file if exists in datastore to clear the way for creating the volume. file: " + volumeDatastorePath);
- VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, vmdkName, dcMo);
+ VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, vmdkName, dcMo, searchExcludedFolders);
vmMo.createDisk(volumeDatastorePath, (int)(volume.getSize() / (1024L * 1024L)), morDatastore, -1);
vmMo.detachDisk(volumeDatastorePath, false);
}
@@ -527,14 +528,14 @@ public Answer cloneVolumeFromBaseTemplate(CopyCommand cmd) {
vmMo.destroy();
String srcFile = dsMo.getDatastorePath(vmdkName, true);
- dsMo.deleteFile(srcFile, dcMo.getMor(), true);
+ dsMo.deleteFile(srcFile, dcMo.getMor(), true, searchExcludedFolders);
}
// restoreVM - move the new ROOT disk into corresponding VM folder
VirtualMachineMO restoreVmMo = dcMo.findVm(volume.getVmName());
if (restoreVmMo != null) {
String vmNameInVcenter = restoreVmMo.getName(); // VM folder name in datastore will be VM's name in vCenter.
if (dsMo.folderExists(String.format("[%s]", dsMo.getName()), vmNameInVcenter)) {
- VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmNameInVcenter, dsMo, vmdkFileBaseName);
+ VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmNameInVcenter, dsMo, vmdkFileBaseName, searchExcludedFolders);
}
}
@@ -631,8 +632,8 @@ public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd) {
}
- private String getVolumePathInDatastore(DatastoreMO dsMo, String volumeFileName) throws Exception {
- String datastoreVolumePath = dsMo.searchFileInSubFolders(volumeFileName, true);
+ private String getVolumePathInDatastore(DatastoreMO dsMo, String volumeFileName, String searchExcludedFolders) throws Exception {
+ String datastoreVolumePath = dsMo.searchFileInSubFolders(volumeFileName, true, searchExcludedFolders);
assert (datastoreVolumePath != null) : "Virtual disk file missing from datastore.";
return datastoreVolumePath;
}
@@ -642,6 +643,7 @@ private String getVolumePathInDatastore(DatastoreMO dsMo, String volumeFileName)
VirtualMachineMO workerVm = null;
VirtualMachineMO vmMo = null;
String exportName = UUID.randomUUID().toString().replace("-", "");
+ String searchExcludedFolders = cmd.getContextParam("searchexludefolders");
try {
ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, poolId);
@@ -665,7 +667,7 @@ private String getVolumePathInDatastore(DatastoreMO dsMo, String volumeFileName)
}
// attach volume to worker VM
- String datastoreVolumePath = getVolumePathInDatastore(dsMo, volumePath + ".vmdk");
+ String datastoreVolumePath = getVolumePathInDatastore(dsMo, volumePath + ".vmdk", searchExcludedFolders);
workerVm.attachDisk(new String[] {datastoreVolumePath}, morDs);
vmMo = workerVm;
}
@@ -690,6 +692,7 @@ public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd) {
VolumeObjectTO srcVolume = (VolumeObjectTO)cmd.getSrcTO();
VolumeObjectTO destVolume = (VolumeObjectTO)cmd.getDestTO();
String vmName = srcVolume.getVmName();
+ String searchExcludedFolders = cmd.getContextParam("searchexludefolders");
VmwareContext context = hostService.getServiceContext(cmd);
try {
@@ -1380,7 +1383,7 @@ private Answer attachVolume(Command cmd, DiskTO disk, boolean isAttach, boolean
if (isManaged) {
datastoreVolumePath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk");
} else {
- datastoreVolumePath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dsMo.getOwnerDatacenter().first(), vmName, dsMo, volumeTO.getPath());
+ datastoreVolumePath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dsMo.getOwnerDatacenter().first(), vmName, dsMo, volumeTO.getPath(), VmwareManager.s_vmwareSearchExcludeFolder.value());
}
} else {
if (isManaged) {
@@ -1415,7 +1418,7 @@ private Answer attachVolume(Command cmd, DiskTO disk, boolean isAttach, boolean
if (isManaged) {
handleDatastoreAndVmdkDetachManaged(diskUuid, iScsiName, storageHost, storagePort);
} else {
- VmwareStorageLayoutHelper.syncVolumeToRootFolder(dsMo.getOwnerDatacenter().first(), dsMo, volumeTO.getPath(), vmName);
+ VmwareStorageLayoutHelper.syncVolumeToRootFolder(dsMo.getOwnerDatacenter().first(), dsMo, volumeTO.getPath(), vmName, VmwareManager.s_vmwareSearchExcludeFolder.value());
}
}
@@ -1591,7 +1594,7 @@ public Answer createVolume(CreateObjectCommand cmd) {
}
catch (Exception e) {
s_logger.error("Deleting file " + volumeDatastorePath + " due to error: " + e.getMessage());
- VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, volumeUuid.toString(), dcMo);
+ VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, volumeUuid.toString(), dcMo, VmwareManager.s_vmwareSearchExcludeFolder.value());
throw new CloudRuntimeException("Unable to create volume due to: " + e.getMessage());
}
}
@@ -1753,7 +1756,7 @@ public Answer deleteVolume(DeleteCommand cmd) {
}
}
- VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, vol.getPath(), new DatacenterMO(context, morDc));
+ VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, vol.getPath(), new DatacenterMO(context, morDc), VmwareManager.s_vmwareSearchExcludeFolder.value());
return new Answer(cmd, true, "Success");
} catch (Throwable e) {
diff --git a/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/VmwareDatacenterApiUnitTest.java b/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/VmwareDatacenterApiUnitTest.java
index fec2aba40f6..e835a0b52af 100644
--- a/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/VmwareDatacenterApiUnitTest.java
+++ b/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/VmwareDatacenterApiUnitTest.java
@@ -17,48 +17,8 @@
package com.cloud.hypervisor.vmware;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-import javax.inject.Inject;
-
-import com.cloud.user.User;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Matchers;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.annotation.ComponentScan.Filter;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.FilterType;
-import org.springframework.core.type.classreading.MetadataReader;
-import org.springframework.core.type.classreading.MetadataReaderFactory;
-import org.springframework.core.type.filter.TypeFilter;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.support.AnnotationConfigContextLoader;
-import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd;
-import org.apache.cloudstack.api.command.admin.zone.RemoveVmwareDcCmd;
-import org.apache.cloudstack.context.CallContext;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
-import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
-import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
-import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao;
-import org.apache.cloudstack.test.utils.SpringUtils;
-
import com.cloud.agent.AgentManager;
+import com.cloud.api.query.dao.TemplateJoinDao;
import com.cloud.cluster.ClusterManager;
import com.cloud.cluster.dao.ManagementServerHostPeerDao;
import com.cloud.dc.ClusterDetailsDao;
@@ -89,15 +49,58 @@
import com.cloud.secstorage.CommandExecLogDao;
import com.cloud.server.ConfigurationServer;
import com.cloud.storage.ImageStoreDetailsUtil;
+import com.cloud.storage.dao.VMTemplatePoolDao;
+import com.cloud.template.TemplateManager;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountService;
import com.cloud.user.AccountVO;
+import com.cloud.user.User;
import com.cloud.user.UserVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.component.ComponentContext;
import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.dao.UserVmCloneSettingDao;
import com.cloud.vm.dao.UserVmDao;
+import com.cloud.vm.dao.VMInstanceDao;
+import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd;
+import org.apache.cloudstack.api.command.admin.zone.RemoveVmwareDcCmd;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
+import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao;
+import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.cloudstack.test.utils.SpringUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.ComponentScan.Filter;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.FilterType;
+import org.springframework.core.type.classreading.MetadataReader;
+import org.springframework.core.type.classreading.MetadataReaderFactory;
+import org.springframework.core.type.filter.TypeFilter;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+import javax.inject.Inject;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import static org.mockito.Mockito.when;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
@@ -447,6 +450,36 @@ public ImageStoreDetailsDao imageStoreDetailsDao() {
return Mockito.mock(ImageStoreDetailsDao.class);
}
+ @Bean
+ public VMTemplatePoolDao templateDataStoreDao() {
+ return Mockito.mock(VMTemplatePoolDao.class);
+ }
+
+ @Bean
+ public TemplateJoinDao templateDao() {
+ return Mockito.mock(TemplateJoinDao.class);
+ }
+
+ @Bean
+ public VMInstanceDao vmInstanceDao() {
+ return Mockito.mock(VMInstanceDao.class);
+ }
+
+ @Bean
+ public UserVmCloneSettingDao cloneSettingDao() {
+ return Mockito.mock(UserVmCloneSettingDao.class);
+ }
+
+ @Bean
+ public PrimaryDataStoreDao primaryStorageDao() {
+ return Mockito.mock(PrimaryDataStoreDao.class);
+ }
+
+ @Bean
+ public TemplateManager templateManager() {
+ return Mockito.mock(TemplateManager.class);
+ }
+
public static class Library implements TypeFilter {
@Override
diff --git a/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java b/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java
index 744c93aa403..c2b3f363883 100644
--- a/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java
+++ b/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java
@@ -58,11 +58,13 @@
import com.vmware.vim25.VirtualDeviceConfigSpec;
import com.vmware.vim25.VirtualMachineConfigSpec;
import com.vmware.vim25.VirtualMachineVideoCard;
+
import com.cloud.agent.api.Command;
import com.cloud.agent.api.ScaleVmAnswer;
import com.cloud.agent.api.ScaleVmCommand;
import com.cloud.agent.api.to.DataTO;
import com.cloud.agent.api.to.NfsTO;
+import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.agent.api.to.VolumeTO;
import com.cloud.hypervisor.vmware.mo.DatacenterMO;
@@ -215,6 +217,38 @@ public void testScaleVMF1() throws Exception {
verify(_resource).execute(cmd);
}
+ @Test
+ public void testGenerateMacSequence() {
+ final NicTO nicTo1 = new NicTO();
+ nicTo1.setMac("01:23:45:67:89:AB");
+ nicTo1.setDeviceId(1);
+
+ final NicTO nicTo2 = new NicTO();
+ nicTo2.setMac("02:00:65:b5:00:03");
+ nicTo2.setDeviceId(0);
+
+ //final NicTO [] nicTOs = {nicTO1, nicTO2, nicTO3};
+ //final NicTO[] nics = new NicTO[]{nic};
+ final NicTO[] nics = new NicTO[] {nicTo1, nicTo2};
+
+ String macSequence = _resource.generateMacSequence(nics);
+ assertEquals(macSequence, "02:00:65:b5:00:03|01:23:45:67:89:AB");
+ }
+
+ @Test
+ public void testReplaceNicsMacSequenceInBootArgs() {
+ String bootArgs = "nic_macs=02:00:65:b5:00:03|7C02:00:4f:1b:00:15|7C1e:00:54:00:00:0f|7C02:00:35:fa:00:11|7C02:00:47:40:00:12";
+ doReturn(bootArgs).when(vmSpec).getBootArgs();
+
+ String oldMacSequence = "7C02:00:35:fa:00:11|7C02:00:47:40:00:12";
+ String newMacSequence = "7C02:00:0c:1d:00:1d|7C02:00:68:0f:00:1e";
+
+ String updatedBootArgs = _resource.replaceNicsMacSequenceInBootArgs(oldMacSequence, newMacSequence, vmSpec);
+
+ String newBootArgs = "nic_macs=02:00:65:b5:00:03|7C02:00:4f:1b:00:15|7C1e:00:54:00:00:0f|7C02:00:0c:1d:00:1d|7C02:00:68:0f:00:1e";
+ assertEquals(newBootArgs, updatedBootArgs);
+ }
+
@Test
public void testConfigureVideoCardSvgaVramProvided() throws Exception {
Map<String, String> specDetails = new HashMap<String, String>();
diff --git a/plugins/hypervisors/xenserver/pom.xml b/plugins/hypervisors/xenserver/pom.xml
index 5ce1b8c41d1..24f1d4e7b90 100644
--- a/plugins/hypervisors/xenserver/pom.xml
+++ b/plugins/hypervisors/xenserver/pom.xml
@@ -16,7 +16,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java
index ccb18a2e55c..f960b9f09b9 100644
--- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java
+++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java
@@ -86,6 +86,7 @@
import com.cloud.utils.script.Script;
import com.cloud.utils.ssh.SSHCmdHelper;
import com.cloud.utils.ssh.SshHelper;
+import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.PowerState;
import com.trilead.ssh2.SCPClient;
import com.xensource.xenapi.Bond;
@@ -1319,6 +1320,18 @@ public VM createVmFromTemplate(final Connection conn, final VirtualMachineTO vmS
vmr.VCPUsAtStartup = (long) vmSpec.getCpus();
vmr.consoles.clear();
+ vmr.xenstoreData.clear();
+ //Add xenstore data for the NetscalerVM
+ if(vmSpec.getType()== VirtualMachine.Type.NetScalerVm) {
+ NicTO mgmtNic = vmSpec.getNics()[0];
+ if(mgmtNic != null ) {
+ Map<String, String> xenstoreData = new HashMap<String, String>(3);
+ xenstoreData.put("vm-data/ip", mgmtNic.getIp().toString().trim());
+ xenstoreData.put("vm-data/gateway", mgmtNic.getGateway().toString().trim());
+ xenstoreData.put("vm-data/netmask", mgmtNic.getNetmask().toString().trim());
+ vmr.xenstoreData = xenstoreData;
+ }
+ }
final VM vm = VM.create(conn, vmr);
if (s_logger.isDebugEnabled()) {
@@ -1329,8 +1342,7 @@ public VM createVmFromTemplate(final Connection conn, final VirtualMachineTO vmS
final Integer speed = vmSpec.getMinSpeed();
if (speed != null) {
-
- int cpuWeight = _maxWeight; // cpu_weight
+ int cpuWeight = _maxWeight; // cpu_weight
int utilization = 0; // max CPU cap, default is unlimited
// weight based allocation, CPU weight is calculated per VCPU
@@ -3321,7 +3333,7 @@ public String getVMInstanceName() {
return _instance;
}
- public long getVMSnapshotChainSize(final Connection conn, final VolumeObjectTO volumeTo, final String vmName) throws BadServerResponse, XenAPIException, XmlRpcException {
+ public long getVMSnapshotChainSize(final Connection conn, final VolumeObjectTO volumeTo, final String vmName, final String vmSnapshotName) throws BadServerResponse, XenAPIException, XmlRpcException {
if (volumeTo.getVolumeType() == Volume.Type.DATADISK) {
final VDI dataDisk = VDI.getByUuid(conn, volumeTo.getPath());
if (dataDisk != null) {
@@ -3352,25 +3364,33 @@ public long getVMSnapshotChainSize(final Connection conn, final VolumeObjectTO v
}
}
if (volumeTo.getVolumeType() == Volume.Type.ROOT) {
- final Map<VM, VM.Record> allVMs = VM.getAllRecords(conn);
- // add size of memory snapshot vdi
- if (allVMs != null && allVMs.size() > 0) {
- for (final VM vmr : allVMs.keySet()) {
- try {
- final String vName = vmr.getNameLabel(conn);
- if (vName != null && vName.contains(vmName) && vmr.getIsASnapshot(conn)) {
- final VDI memoryVDI = vmr.getSuspendVDI(conn);
- if (!isRefNull(memoryVDI)) {
- size = size + memoryVDI.getPhysicalUtilisation(conn);
- final VDI pMemoryVDI = memoryVDI.getParent(conn);
- if (!isRefNull(pMemoryVDI)) {
- size = size + pMemoryVDI.getPhysicalUtilisation(conn);
+ VM vm = getVM(conn, vmName);
+ if(vm != null){
+ Set<VM> vmSnapshots=vm.getSnapshots(conn);
+ if(vmSnapshots != null){
+ for(VM vmsnap: vmSnapshots){
+ try {
+ final String vmSnapName = vmsnap.getNameLabel(conn);
+ s_logger.debug("snapname " + vmSnapName);
+ if (vmSnapName != null && vmSnapName.contains(vmSnapshotName) && vmsnap.getIsASnapshot(conn)) {
+ s_logger.debug("snapname " + vmSnapName + "isASnapshot");
+ VDI memoryVDI = vmsnap.getSuspendVDI(conn);
+ if (!isRefNull(memoryVDI)) {
+ size = size + memoryVDI.getPhysicalUtilisation(conn);
+ s_logger.debug("memoryVDI size :"+size);
+ String parentUuid = memoryVDI.getSmConfig(conn).get("vhd-parent");
+ VDI pMemoryVDI = VDI.getByUuid(conn, parentUuid);
+ if (!isRefNull(pMemoryVDI)) {
+ size = size + pMemoryVDI.getPhysicalUtilisation(conn);
+ }
+ s_logger.debug("memoryVDI size+parent :"+size);
}
}
+ } catch (Exception e) {
+ s_logger.debug("Exception occurs when calculate snapshot capacity for memory: due to " + e.toString());
+ continue;
}
- } catch (final Exception e) {
- s_logger.debug("Exception occurs when calculate snapshot capacity for memory: due to " + e.toString());
- continue;
+
}
}
}
diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServerStorageProcessor.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServerStorageProcessor.java
index 26f7e9cdf90..d6697322857 100644
--- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServerStorageProcessor.java
+++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServerStorageProcessor.java
@@ -25,7 +25,6 @@
import com.cloud.agent.api.to.DiskTO;
import com.cloud.agent.api.to.NfsTO;
import com.cloud.agent.api.to.S3TO;
-import com.cloud.agent.api.to.StorageFilerTO;
import com.cloud.agent.api.to.SwiftTO;
import com.cloud.exception.InternalErrorException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
@@ -36,12 +35,7 @@
import com.cloud.storage.resource.StorageProcessor;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.storage.S3.ClientOptions;
-import com.cloud.utils.storage.encoding.DecodedDataObject;
-import com.cloud.utils.storage.encoding.DecodedDataStore;
-import com.cloud.utils.storage.encoding.Decoder;
import com.xensource.xenapi.Connection;
-import com.xensource.xenapi.Host;
-import com.xensource.xenapi.PBD;
import com.xensource.xenapi.SR;
import com.xensource.xenapi.Types;
import com.xensource.xenapi.Types.BadServerResponse;
@@ -52,8 +46,6 @@
import com.xensource.xenapi.VM;
import org.apache.cloudstack.storage.command.AttachAnswer;
import org.apache.cloudstack.storage.command.AttachCommand;
-import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreAnswer;
-import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd;
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
import org.apache.cloudstack.storage.command.CopyCommand;
import org.apache.cloudstack.storage.command.CreateObjectAnswer;
@@ -68,7 +60,6 @@
import org.apache.cloudstack.storage.command.ResignatureCommand;
import org.apache.cloudstack.storage.command.SnapshotAndCopyAnswer;
import org.apache.cloudstack.storage.command.SnapshotAndCopyCommand;
-import org.apache.cloudstack.storage.datastore.protocol.DataStoreProtocol;
import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
import org.apache.cloudstack.storage.to.TemplateObjectTO;
@@ -475,15 +466,6 @@ public Answer dettachVolume(final DettachCommand cmd) {
}
}
- protected SR getSRByNameLabel(final Connection conn, final String nameLabel) throws BadServerResponse, XenAPIException, XmlRpcException {
- final Set<SR> srs = SR.getByNameLabel(conn, nameLabel);
- if (srs.size() != 1) {
- throw new CloudRuntimeException("storage uuid: " + nameLabel + " is not unique");
- }
- final SR poolsr = srs.iterator().next();
- return poolsr;
- }
-
protected VDI createVdi(final Connection conn, final String vdiName, final SR sr, final long size) throws BadServerResponse, XenAPIException, XmlRpcException {
final VDI.Record vdir = new VDI.Record();
vdir.nameLabel = vdiName;
@@ -578,161 +560,6 @@ public Answer deleteVolume(final DeleteCommand cmd) {
return new Answer(null, false, errorMsg);
}
- protected SR getNfsSR(final Connection conn, final StorageFilerTO pool) {
- final Map<String, String> deviceConfig = new HashMap<String, String>();
- try {
- final String server = pool.getHost();
- String serverpath = pool.getPath();
- serverpath = serverpath.replace("//", "/");
- final Set<SR> srs = SR.getAll(conn);
- for (final SR sr : srs) {
- if (!SRType.NFS.equals(sr.getType(conn))) {
- continue;
- }
-
- final Set<PBD> pbds = sr.getPBDs(conn);
- if (pbds.isEmpty()) {
- continue;
- }
-
- final PBD pbd = pbds.iterator().next();
-
- final Map<String, String> dc = pbd.getDeviceConfig(conn);
-
- if (dc == null) {
- continue;
- }
-
- if (dc.get("server") == null) {
- continue;
- }
-
- if (dc.get("serverpath") == null) {
- continue;
- }
-
- if (server.equals(dc.get("server")) && serverpath.equals(dc.get("serverpath"))) {
- throw new CloudRuntimeException("There is a SR using the same configuration server:" + dc.get("server") + ", serverpath:" + dc.get("serverpath") +
- " for pool " + pool.getUuid() + "on host:" + hypervisorResource.getHost().getUuid());
- }
-
- }
- deviceConfig.put("server", server);
- deviceConfig.put("serverpath", serverpath);
- final Host host = Host.getByUuid(conn, hypervisorResource.getHost().getUuid());
- final Map<String, String> smConfig = new HashMap<String, String>();
- smConfig.put("nosubdir", "true");
- final SR sr = SR.create(conn, host, deviceConfig, new Long(0), pool.getUuid(), Long.toString(pool.getId()), SRType.NFS.toString(), "user", true, smConfig);
- sr.scan(conn);
- return sr;
- } catch (final XenAPIException e) {
- throw new CloudRuntimeException("Unable to create NFS SR " + pool.toString(), e);
- } catch (final XmlRpcException e) {
- throw new CloudRuntimeException("Unable to create NFS SR " + pool.toString(), e);
- }
- }
-
- protected Answer directDownloadHttpTemplate(final CopyCommand cmd, final DecodedDataObject srcObj, final DecodedDataObject destObj) {
- final Connection conn = hypervisorResource.getConnection();
- SR poolsr = null;
- VDI vdi = null;
- boolean result = false;
- try {
- if (destObj.getPath() == null) {
- //need to create volume at first
-
- }
- vdi = VDI.getByUuid(conn, destObj.getPath());
- if (vdi == null) {
- throw new CloudRuntimeException("can't find volume: " + destObj.getPath());
- }
- final String destStoreUuid = destObj.getStore().getUuid();
- final Set<SR> srs = SR.getByNameLabel(conn, destStoreUuid);
- if (srs.size() != 1) {
- throw new CloudRuntimeException("storage uuid: " + destStoreUuid + " is not unique");
- }
- poolsr = srs.iterator().next();
- final VDI.Record vdir = vdi.getRecord(conn);
- final String vdiLocation = vdir.location;
- String pbdLocation = null;
- if (destObj.getStore().getScheme().equalsIgnoreCase(DataStoreProtocol.NFS.toString())) {
- pbdLocation = "/run/sr-mount/" + poolsr.getUuid(conn);
- } else {
- final Set<PBD> pbds = poolsr.getPBDs(conn);
- if (pbds.size() != 1) {
- throw new CloudRuntimeException("Don't how to handle multiple pbds:" + pbds.size() + " for sr: " + poolsr.getUuid(conn));
- }
- final PBD pbd = pbds.iterator().next();
- final Map<String, String> deviceCfg = pbd.getDeviceConfig(conn);
- pbdLocation = deviceCfg.get("location");
- }
- if (pbdLocation == null) {
- throw new CloudRuntimeException("Can't get pbd location");
- }
-
- final String vdiPath = pbdLocation + "/" + vdiLocation + ".vhd";
- //download a url into vdipath
- //downloadHttpToLocalFile(vdiPath, template.getPath());
- hypervisorResource.callHostPlugin(conn, "storagePlugin", "downloadTemplateFromUrl", "destPath", vdiPath, "srcUrl", srcObj.getPath());
- result = true;
- //return new CopyCmdAnswer(cmd, vdi.getUuid(conn));
- } catch (final BadServerResponse e) {
- s_logger.debug("Failed to download template", e);
- } catch (final XenAPIException e) {
- s_logger.debug("Failed to download template", e);
- } catch (final XmlRpcException e) {
- s_logger.debug("Failed to download template", e);
- } catch (final Exception e) {
- s_logger.debug("Failed to download template", e);
- } finally {
- if (!result && vdi != null) {
- try {
- vdi.destroy(conn);
- } catch (final BadServerResponse e) {
- s_logger.debug("Failed to cleanup newly created vdi");
- } catch (final XenAPIException e) {
- s_logger.debug("Failed to cleanup newly created vdi");
- } catch (final XmlRpcException e) {
- s_logger.debug("Failed to cleanup newly created vdi");
- }
- }
- }
- return new Answer(cmd, false, "Failed to download template");
- }
-
- protected Answer execute(final AttachPrimaryDataStoreCmd cmd) {
- final String dataStoreUri = cmd.getDataStore();
- final Connection conn = hypervisorResource.getConnection();
- try {
- final DecodedDataObject obj = Decoder.decode(dataStoreUri);
-
- final DecodedDataStore store = obj.getStore();
-
- final SR sr = hypervisorResource.getStorageRepository(conn, store.getUuid());
- hypervisorResource.setupHeartbeatSr(conn, sr, false);
- final long capacity = sr.getPhysicalSize(conn);
- final long available = capacity - sr.getPhysicalUtilisation(conn);
- if (capacity == -1) {
- final String msg = "Pool capacity is -1! pool: ";
- s_logger.warn(msg);
- return new Answer(cmd, false, msg);
- }
- final AttachPrimaryDataStoreAnswer answer = new AttachPrimaryDataStoreAnswer(cmd);
- answer.setCapacity(capacity);
- answer.setUuid(sr.getUuid(conn));
- answer.setAvailable(available);
- return answer;
- } catch (final XenAPIException e) {
- final String msg = "AttachPrimaryDataStoreCmd add XenAPIException:" + e.toString();
- s_logger.warn(msg, e);
- return new Answer(cmd, false, msg);
- } catch (final Exception e) {
- final String msg = "AttachPrimaryDataStoreCmd failed:" + e.getMessage();
- s_logger.warn(msg, e);
- return new Answer(cmd, false, msg);
- }
- }
-
protected boolean IsISCSI(final String type) {
return SRType.LVMOHBA.equals(type) || SRType.LVMOISCSI.equals(type) || SRType.LVM.equals(type);
}
@@ -1072,7 +899,8 @@ public Answer copyVolumeFromPrimaryToSecondary(final CopyCommand cmd) {
return new CopyCmdAnswer("unsupported protocol");
}
- boolean swiftUpload(final Connection conn, final SwiftTO swift, final String container, final String ldir, final String lfilename, final Boolean isISCSI, final int wait) {
+ private boolean swiftUpload(final Connection conn, final SwiftTO swift, final String container, final String ldir, final String lfilename, final Boolean isISCSI,
+ final int wait) {
String result = null;
try {
result =
@@ -1097,7 +925,8 @@ protected String deleteSnapshotBackup(final Connection conn, final String localM
return result;
}
- public String swiftBackupSnapshot(final Connection conn, final SwiftTO swift, final String srUuid, final String snapshotUuid, final String container, final Boolean isISCSI, final int wait) {
+ protected String swiftBackupSnapshot(final Connection conn, final SwiftTO swift, final String srUuid, final String snapshotUuid, final String container, final Boolean isISCSI,
+ final int wait) {
String lfilename;
String ldir;
if (isISCSI) {
@@ -1141,7 +970,7 @@ protected String backupSnapshotToS3(final Connection connection, final S3TO s3,
}
- protected Long getSnapshotSize(final Connection conn, final String primaryStorageSRUuid, final String snapshotUuid, final Boolean isISCSI, final int wait) {
+ private Long getSnapshotSize(final Connection conn, final String primaryStorageSRUuid, final String snapshotUuid, final Boolean isISCSI, final int wait) {
final String physicalSize = hypervisorResource.callHostPluginAsync(conn, "vmopsSnapshot", "getSnapshotSize", wait,
"primaryStorageSRUuid", primaryStorageSRUuid, "snapshotUuid", snapshotUuid, "isISCSI", isISCSI.toString());
if (physicalSize == null || physicalSize.isEmpty()) {
@@ -1151,7 +980,7 @@ protected Long getSnapshotSize(final Connection conn, final String primaryStorag
}
}
- protected String backupSnapshot(final Connection conn, final String primaryStorageSRUuid, final String localMountPoint, final String path, final String secondaryStorageMountPath,
+ private String backupSnapshot(final Connection conn, final String primaryStorageSRUuid, final String localMountPoint, final String path, final String secondaryStorageMountPath,
final String snapshotUuid, String prevBackupUuid, final Boolean isISCSI, final int wait) {
String backupSnapshotUuid = null;
diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixCreateVMSnapshotCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixCreateVMSnapshotCommandWrapper.java
index 4550cf8b637..6bd843dadf0 100644
--- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixCreateVMSnapshotCommandWrapper.java
+++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixCreateVMSnapshotCommandWrapper.java
@@ -23,6 +23,7 @@
import java.util.List;
import java.util.Set;
+import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.storage.to.VolumeObjectTO;
import org.apache.log4j.Logger;
@@ -142,8 +143,11 @@ public Answer execute(final CreateVMSnapshotCommand command, final CitrixResourc
}
// calculate used capacity for this VM snapshot
for (final VolumeObjectTO volumeTo : command.getVolumeTOs()) {
- final long size = citrixResourceBase.getVMSnapshotChainSize(conn, volumeTo, command.getVmName());
- volumeTo.setSize(size);
+ try {
+ final long size = citrixResourceBase.getVMSnapshotChainSize(conn, volumeTo, command.getVmName(), vmSnapshotName);
+ volumeTo.setSize(size);
+ } catch (final CloudRuntimeException cre) {
+ }
}
success = true;
diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixDeleteVMSnapshotCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixDeleteVMSnapshotCommandWrapper.java
index a341c76b057..3aeeb4249da 100644
--- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixDeleteVMSnapshotCommandWrapper.java
+++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixDeleteVMSnapshotCommandWrapper.java
@@ -23,6 +23,7 @@
import java.util.List;
import java.util.Set;
+import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.storage.to.VolumeObjectTO;
import org.apache.log4j.Logger;
@@ -79,8 +80,12 @@ public Answer execute(final DeleteVMSnapshotCommand command, final CitrixResourc
}
// re-calculate used capacify for this VM snapshot
for (final VolumeObjectTO volumeTo : command.getVolumeTOs()) {
- final long size = citrixResourceBase.getVMSnapshotChainSize(conn, volumeTo, command.getVmName());
- volumeTo.setSize(size);
+ try {
+ final long size = citrixResourceBase.getVMSnapshotChainSize(conn, volumeTo, command.getVmName(), snapshotName);
+ volumeTo.setSize(size);
+ } catch (final CloudRuntimeException cre) {
+
+ }
}
return new DeleteVMSnapshotAnswer(command, command.getVolumeTOs());
diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixGetVmNetworkStatsCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixGetVmNetworkStatsCommandWrapper.java
new file mode 100644
index 00000000000..45cacf1500f
--- /dev/null
+++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixGetVmNetworkStatsCommandWrapper.java
@@ -0,0 +1,36 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package com.cloud.hypervisor.xenserver.resource.wrapper.xenbase;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.GetVmNetworkStatsAnswer;
+import com.cloud.agent.api.GetVmNetworkStatsCommand;
+import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase;
+import com.cloud.resource.CommandWrapper;
+import com.cloud.resource.ResourceWrapper;
+
+@ResourceWrapper(handles = GetVmNetworkStatsCommand.class)
+public final class CitrixGetVmNetworkStatsCommandWrapper extends CommandWrapper<GetVmNetworkStatsCommand, Answer, CitrixResourceBase> {
+
+ @Override
+ public Answer execute(final GetVmNetworkStatsCommand command, final CitrixResourceBase citrixResourceBase) {
+ return new GetVmNetworkStatsAnswer(command, null, null, null);
+ }
+}
\ No newline at end of file
diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java
index 073f00096b0..5d8d0e744db 100644
--- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java
+++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java
@@ -87,7 +87,6 @@ public Answer execute(final StartCommand command, final CitrixResourceBase citri
final Host host = Host.getByUuid(conn, citrixResourceBase.getHost().getUuid());
vm = citrixResourceBase.createVmFromTemplate(conn, vmSpec, host);
-
final GPUDeviceTO gpuDevice = vmSpec.getGpuDevice();
if (gpuDevice != null) {
s_logger.debug("Creating VGPU for of VGPU type: " + gpuDevice.getVgpuType() + " in GPU group " + gpuDevice.getGpuGroup() + " for VM " + vmName);
diff --git a/plugins/integrations/cloudian/pom.xml b/plugins/integrations/cloudian/pom.xml
new file mode 100644
index 00000000000..3e2b63562fb
--- /dev/null
+++ b/plugins/integrations/cloudian/pom.xml
@@ -0,0 +1,60 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+ http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>cloud-plugin-integrations-cloudian-connector</artifactId>
+ <name>Apache CloudStack Plugin - Cloudian Connector</name>
+ <parent>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloudstack-plugins</artifactId>
+ <version>4.11.0.0-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-utils</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>${cs.httpclient.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>${cs.jackson.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.github.tomakehurst</groupId>
+ <artifactId>wiremock</artifactId>
+ <version>${cs.wiremock.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/packaging/fedora20/tomcat.sh b/plugins/integrations/cloudian/resources/META-INF/cloudstack/cloudian/module.properties
similarity index 96%
rename from packaging/fedora20/tomcat.sh
rename to plugins/integrations/cloudian/resources/META-INF/cloudstack/cloudian/module.properties
index 76ba7419a53..762c636cd3b 100644
--- a/packaging/fedora20/tomcat.sh
+++ b/plugins/integrations/cloudian/resources/META-INF/cloudstack/cloudian/module.properties
@@ -14,5 +14,5 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-
-service tomcat start
+name=cloudian
+parent=api
diff --git a/plugins/integrations/cloudian/resources/META-INF/cloudstack/cloudian/spring-cloudian-context.xml b/plugins/integrations/cloudian/resources/META-INF/cloudstack/cloudian/spring-cloudian-context.xml
new file mode 100644
index 00000000000..71ed52dd701
--- /dev/null
+++ b/plugins/integrations/cloudian/resources/META-INF/cloudstack/cloudian/spring-cloudian-context.xml
@@ -0,0 +1,25 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd">
+ <bean id="cloudianConnector" class="org.apache.cloudstack.cloudian.CloudianConnectorImpl" >
+ </bean>
+</beans>
diff --git a/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/CloudianConnector.java b/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/CloudianConnector.java
new file mode 100644
index 00000000000..c04d70c2601
--- /dev/null
+++ b/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/CloudianConnector.java
@@ -0,0 +1,82 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.cloudian;
+
+import org.apache.cloudstack.framework.config.ConfigKey;
+
+import com.cloud.utils.component.PluggableService;
+
+public interface CloudianConnector extends PluggableService {
+
+ ConfigKey<Boolean> CloudianConnectorEnabled = new ConfigKey<>("Advanced", Boolean.class, "cloudian.connector.enabled", "false",
+ "If set to true, this enables the Cloudian Connector for CloudStack.", true);
+
+ ConfigKey<String> CloudianAdminHost = new ConfigKey<>("Advanced", String.class, "cloudian.admin.host", "s3-admin.cloudian.com",
+ "The hostname of the Cloudian Admin server.", true);
+
+ ConfigKey<Integer> CloudianAdminPort = new ConfigKey<>("Advanced", Integer.class, "cloudian.admin.port", "19443",
+ "The port of the Cloudian Admin server.", true);
+
+ ConfigKey<String> CloudianAdminProtocol = new ConfigKey<>("Advanced", String.class, "cloudian.admin.protocol", "https",
+ "The protocol of the Cloudian Admin server.", true);
+
+ ConfigKey<Boolean> CloudianValidateSSLSecurity = new ConfigKey<>("Advanced", Boolean.class, "cloudian.validate.ssl", "true",
+ "When set to true, this will validate the SSL certificate when connecting to https/ssl enabled admin host.", true);
+
+ ConfigKey<String> CloudianAdminUser = new ConfigKey<>("Advanced", String.class, "cloudian.admin.user", "sysadmin",
+ "The system admin user for accessing the Cloudian Admin server.", true);
+
+ ConfigKey<String> CloudianAdminPassword = new ConfigKey<>("Advanced", String.class, "cloudian.admin.password", "public",
+ "The system admin password for the Cloudian Admin server.", true);
+
+ ConfigKey<Integer> CloudianAdminApiRequestTimeout = new ConfigKey<>("Advanced", Integer.class, "cloudian.api.request.timeout", "5",
+ "The admin API request timeout in seconds.", true);
+
+ ConfigKey<String> CloudianCmcAdminUser = new ConfigKey<>("Advanced", String.class, "cloudian.cmc.admin.user", "admin",
+ "The admin user name for accessing the Cloudian Management Console.", true);
+
+ ConfigKey<String> CloudianCmcHost = new ConfigKey<>("Advanced", String.class, "cloudian.cmc.host", "cmc.cloudian.com",
+ "The hostname of the Cloudian Management Console.", true);
+
+ ConfigKey<String> CloudianCmcPort = new ConfigKey<>("Advanced", String.class, "cloudian.cmc.port", "8443",
+ "The port of the Cloudian Management Console.", true);
+
+ ConfigKey<String> CloudianCmcProtocol = new ConfigKey<>("Advanced", String.class, "cloudian.cmc.protocol", "https",
+ "The protocol of the Cloudian Management Console.", true);
+
+ ConfigKey<String> CloudianSsoKey = new ConfigKey<>("Advanced", String.class, "cloudian.sso.key", "ss0sh5r3dk3y",
+ "The shared single sign-on key as configured in Cloudian CMC.", true);
+
+ /**
+ * Returns the base Cloudian Management Console URL
+ * @return returns the url string
+ */
+ String getCmcUrl();
+
+ /**
+ * Checks if the Cloudian Connector is enabled
+ * @return returns true is connector is enabled
+ */
+ boolean isEnabled();
+
+ /**
+ * Generates single-sign on URL for logged in user
+ * @return returns the SSO URL string
+ */
+ String generateSsoUrl();
+}
diff --git a/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/CloudianConnectorImpl.java b/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/CloudianConnectorImpl.java
new file mode 100644
index 00000000000..cfb23da2846
--- /dev/null
+++ b/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/CloudianConnectorImpl.java
@@ -0,0 +1,345 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.cloudian;
+
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.cloudian.api.CloudianIsEnabledCmd;
+import org.apache.cloudstack.cloudian.api.CloudianSsoLoginCmd;
+import org.apache.cloudstack.cloudian.client.CloudianClient;
+import org.apache.cloudstack.cloudian.client.CloudianGroup;
+import org.apache.cloudstack.cloudian.client.CloudianUser;
+import org.apache.cloudstack.cloudian.client.CloudianUtils;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.Configurable;
+import org.apache.cloudstack.framework.messagebus.MessageBus;
+import org.apache.cloudstack.framework.messagebus.MessageSubscriber;
+import org.apache.log4j.Logger;
+
+import com.cloud.domain.Domain;
+import com.cloud.domain.DomainVO;
+import com.cloud.domain.dao.DomainDao;
+import com.cloud.user.Account;
+import com.cloud.user.AccountManager;
+import com.cloud.user.DomainManager;
+import com.cloud.user.User;
+import com.cloud.user.dao.AccountDao;
+import com.cloud.user.dao.UserDao;
+import com.cloud.utils.component.ComponentLifecycleBase;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+public class CloudianConnectorImpl extends ComponentLifecycleBase implements CloudianConnector, Configurable {
+ private static final Logger LOG = Logger.getLogger(CloudianConnectorImpl.class);
+
+ @Inject
+ private UserDao userDao;
+
+ @Inject
+ private AccountDao accountDao;
+
+ @Inject
+ private DomainDao domainDao;
+
+ @Inject
+ private MessageBus messageBus;
+
+ /////////////////////////////////////////////////////
+ //////////////// Plugin Methods /////////////////////
+ /////////////////////////////////////////////////////
+
+ private CloudianClient getClient() {
+ try {
+ return new CloudianClient(CloudianAdminHost.value(), CloudianAdminPort.value(), CloudianAdminProtocol.value(),
+ CloudianAdminUser.value(), CloudianAdminPassword.value(),
+ CloudianValidateSSLSecurity.value(), CloudianAdminApiRequestTimeout.value());
+ } catch (final KeyStoreException | NoSuchAlgorithmException | KeyManagementException e) {
+ LOG.error("Failed to create Cloudian API client due to: ", e);
+ }
+ throw new CloudRuntimeException("Failed to create and return Cloudian API client instance");
+ }
+
+ private boolean addGroup(final Domain domain) {
+ if (domain == null || !isEnabled()) {
+ return false;
+ }
+ final CloudianClient client = getClient();
+ final CloudianGroup group = new CloudianGroup();
+ group.setGroupId(domain.getUuid());
+ group.setGroupName(domain.getPath());
+ group.setActive(true);
+ return client.addGroup(group);
+ }
+
+ private boolean removeGroup(final Domain domain) {
+ if (domain == null || !isEnabled()) {
+ return false;
+ }
+ final CloudianClient client = getClient();
+ for (final CloudianUser user: client.listUsers(domain.getUuid())) {
+ if (client.removeUser(user.getUserId(), domain.getUuid())) {
+ LOG.error(String.format("Failed to remove Cloudian user id=%s, while removing Cloudian group id=%s", user.getUserId(), domain.getUuid()));
+ }
+ }
+ for (int retry = 0; retry < 3; retry++) {
+ if (client.removeGroup(domain.getUuid())) {
+ return true;
+ } else {
+ LOG.warn("Failed to remove Cloudian group id=" + domain.getUuid() + ", retrying count=" + retry+1);
+ }
+ }
+ LOG.warn("Failed to remove Cloudian group id=" + domain.getUuid() + ", please remove manually");
+ return false;
+ }
+
+ private boolean addUserAccount(final Account account, final Domain domain) {
+ if (account == null || domain == null || !isEnabled()) {
+ return false;
+ }
+ final User accountUser = userDao.listByAccount(account.getId()).get(0);
+ final CloudianClient client = getClient();
+ final String fullName = String.format("%s %s (%s)", accountUser.getFirstname(), accountUser.getLastname(), account.getAccountName());
+ final CloudianUser user = new CloudianUser();
+ user.setUserId(account.getUuid());
+ user.setGroupId(domain.getUuid());
+ user.setFullName(fullName);
+ user.setEmailAddr(accountUser.getEmail());
+ user.setUserType(CloudianUser.USER);
+ user.setActive(true);
+ return client.addUser(user);
+ }
+
+ private boolean updateUserAccount(final Account account, final Domain domain, final CloudianUser existingUser) {
+ if (account == null || domain == null || !isEnabled()) {
+ return false;
+ }
+ final CloudianClient client = getClient();
+ if (existingUser != null) {
+ final User accountUser = userDao.listByAccount(account.getId()).get(0);
+ final String fullName = String.format("%s %s (%s)", accountUser.getFirstname(), accountUser.getLastname(), account.getAccountName());
+ if (!existingUser.getActive() || !existingUser.getFullName().equals(fullName) || !existingUser.getEmailAddr().equals(accountUser.getEmail())) {
+ existingUser.setActive(true);
+ existingUser.setFullName(fullName);
+ existingUser.setEmailAddr(accountUser.getEmail());
+ return client.updateUser(existingUser);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private boolean removeUserAccount(final Account account) {
+ if (account == null || !isEnabled()) {
+ return false;
+ }
+ final CloudianClient client = getClient();
+ final Domain domain = domainDao.findById(account.getDomainId());
+ for (int retry = 0; retry < 3; retry++) {
+ if (client.removeUser(account.getUuid(), domain.getUuid())) {
+ return true;
+ } else {
+ LOG.warn("Failed to remove Cloudian user id=" + account.getUuid() + " in group id=" + domain.getUuid() + ", retrying count=" + retry+1);
+ }
+ }
+ LOG.warn("Failed to remove Cloudian user id=" + account.getUuid() + " in group id=" + domain.getUuid() + ", please remove manually");
+ return false;
+ }
+
+ //////////////////////////////////////////////////
+ //////////////// Plugin APIs /////////////////////
+ //////////////////////////////////////////////////
+
+ @Override
+ public String getCmcUrl() {
+ return String.format("%s://%s:%s/Cloudian/", CloudianCmcProtocol.value(),
+ CloudianCmcHost.value(), CloudianCmcPort.value());
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return CloudianConnectorEnabled.value();
+ }
+
+ @Override
+ public String generateSsoUrl() {
+ final Account caller = CallContext.current().getCallingAccount();
+ final Domain domain = domainDao.findById(caller.getDomainId());
+
+ String user = caller.getUuid();
+ String group = domain.getUuid();
+
+ if (caller.getAccountName().equals("admin") && caller.getRoleId() == RoleType.Admin.getId()) {
+ user = CloudianCmcAdminUser.value();
+ group = "0";
+ }
+
+ LOG.debug(String.format("Attempting Cloudian SSO with user id=%s, group id=%s", user, group));
+
+ final CloudianUser ssoUser = getClient().listUser(user, group);
+ if (ssoUser == null || !ssoUser.getActive()) {
+ LOG.debug(String.format("Failed to find existing Cloudian user id=%s in group id=%s", user, group));
+ final CloudianGroup ssoGroup = getClient().listGroup(group);
+ if (ssoGroup == null) {
+ LOG.debug(String.format("Failed to find existing Cloudian group id=%s, trying to add it", group));
+ if (!addGroup(domain)) {
+ LOG.error("Failed to add missing Cloudian group id=" + group);
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Aborting Cloudian SSO, failed to add group to Cloudian.");
+ }
+ }
+ if (!addUserAccount(caller, domain)) {
+ LOG.error("Failed to add missing Cloudian group id=" + group);
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Aborting Cloudian SSO, failed to add user to Cloudian.");
+ }
+ final CloudianUser addedSsoUser = getClient().listUser(user, group);
+ if (addedSsoUser == null || !addedSsoUser.getActive()) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Aborting Cloudian SSO, failed to find mapped Cloudian user, please fix integration issues.");
+ }
+ } else if (!group.equals("0")) {
+ updateUserAccount(caller, domain, ssoUser);
+ }
+
+ LOG.debug(String.format("Validated Cloudian SSO for Cloudian user id=%s, group id=%s", user, group));
+ return CloudianUtils.generateSSOUrl(getCmcUrl(), user, group, CloudianSsoKey.value());
+ }
+
+ ///////////////////////////////////////////////////////////
+ //////////////// Plugin Configuration /////////////////////
+ ///////////////////////////////////////////////////////////
+
+ @Override
+ public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+ super.configure(name, params);
+
+ if (!isEnabled()) {
+ LOG.debug("Cloudian connector is disabled, skipping configuration");
+ return true;
+ }
+
+ LOG.debug(String.format("Cloudian connector is enabled, completed configuration, integration is ready. " +
+ "Cloudian admin host:%s, port:%s, user:%s",
+ CloudianAdminHost.value(), CloudianAdminPort.value(), CloudianAdminUser.value()));
+
+ messageBus.subscribe(AccountManager.MESSAGE_ADD_ACCOUNT_EVENT, new MessageSubscriber() {
+ @Override
+ public void onPublishMessage(String senderAddress, String subject, Object args) {
+ try {
+ final Map<Long, Long> accountGroupMap = (Map<Long, Long>) args;
+ final Long accountId = accountGroupMap.keySet().iterator().next();
+ final Account account = accountDao.findById(accountId);
+ final Domain domain = domainDao.findById(account.getDomainId());
+
+ if (!addUserAccount(account, domain)) {
+ LOG.warn(String.format("Failed to add account in Cloudian while adding CloudStack account=%s in domain=%s", account.getAccountName(), domain.getPath()));
+ }
+ } catch (final Exception e) {
+ LOG.error("Caught exception while adding account in Cloudian: ", e);
+ }
+ }
+ });
+
+ messageBus.subscribe(AccountManager.MESSAGE_REMOVE_ACCOUNT_EVENT, new MessageSubscriber() {
+ @Override
+ public void onPublishMessage(String senderAddress, String subject, Object args) {
+ try {
+ final Account account = accountDao.findByIdIncludingRemoved((Long) args);
+ if(!removeUserAccount(account)) {
+ LOG.warn(String.format("Failed to remove account to Cloudian while removing CloudStack account=%s, id=%s", account.getAccountName(), account.getId()));
+ }
+ } catch (final Exception e) {
+ LOG.error("Caught exception while removing account in Cloudian: ", e);
+ }
+ }
+ });
+
+ messageBus.subscribe(DomainManager.MESSAGE_ADD_DOMAIN_EVENT, new MessageSubscriber() {
+ @Override
+ public void onPublishMessage(String senderAddress, String subject, Object args) {
+ try {
+ final Domain domain = domainDao.findById((Long) args);
+ if (!addGroup(domain)) {
+ LOG.warn(String.format("Failed to add group in Cloudian while adding CloudStack domain=%s id=%s", domain.getPath(), domain.getId()));
+ }
+ } catch (final Exception e) {
+ LOG.error("Caught exception adding domain/group in Cloudian: ", e);
+ }
+ }
+ });
+
+ messageBus.subscribe(DomainManager.MESSAGE_REMOVE_DOMAIN_EVENT, new MessageSubscriber() {
+ @Override
+ public void onPublishMessage(String senderAddress, String subject, Object args) {
+ try {
+ final DomainVO domain = (DomainVO) args;
+ if (!removeGroup(domain)) {
+ LOG.warn(String.format("Failed to remove group in Cloudian while removing CloudStack domain=%s id=%s", domain.getPath(), domain.getId()));
+ }
+ } catch (final Exception e) {
+ LOG.error("Caught exception while removing domain/group in Cloudian: ", e);
+ }
+ }
+ });
+
+ return true;
+ }
+
+ @Override
+ public List<Class<?>> getCommands() {
+ final List<Class<?>> cmdList = new ArrayList<Class<?>>();
+ cmdList.add(CloudianIsEnabledCmd.class);
+ if (!isEnabled()) {
+ return cmdList;
+ }
+ cmdList.add(CloudianSsoLoginCmd.class);
+ return cmdList;
+ }
+
+ @Override
+ public String getConfigComponentName() {
+ return CloudianConnector.class.getSimpleName();
+ }
+
+ @Override
+ public ConfigKey<?>[] getConfigKeys() {
+ return new ConfigKey<?>[] {
+ CloudianConnectorEnabled,
+ CloudianAdminHost,
+ CloudianAdminPort,
+ CloudianAdminUser,
+ CloudianAdminPassword,
+ CloudianAdminProtocol,
+ CloudianAdminApiRequestTimeout,
+ CloudianValidateSSLSecurity,
+ CloudianCmcAdminUser,
+ CloudianCmcHost,
+ CloudianCmcPort,
+ CloudianCmcProtocol,
+ CloudianSsoKey
+ };
+ }
+}
diff --git a/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/api/CloudianIsEnabledCmd.java b/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/api/CloudianIsEnabledCmd.java
new file mode 100644
index 00000000000..fdca87185d0
--- /dev/null
+++ b/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/api/CloudianIsEnabledCmd.java
@@ -0,0 +1,65 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.cloudian.api;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.cloudian.CloudianConnector;
+import org.apache.cloudstack.cloudian.response.CloudianEnabledResponse;
+
+import com.cloud.user.Account;
+
+@APICommand(name = CloudianIsEnabledCmd.APINAME, description = "Checks if the Cloudian Connector is enabled",
+ responseObject = CloudianEnabledResponse.class,
+ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
+ since = "4.11.0",
+ authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
+public class CloudianIsEnabledCmd extends BaseCmd {
+ public static final String APINAME = "cloudianIsEnabled";
+
+ @Inject
+ private CloudianConnector connector;
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+
+ @Override
+ public void execute() {
+ final CloudianEnabledResponse response = new CloudianEnabledResponse();
+ response.setEnabled(connector.isEnabled());
+ response.setCmcUrl(connector.getCmcUrl());
+ response.setObjectName(APINAME.toLowerCase());
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ }
+}
diff --git a/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/api/CloudianSsoLoginCmd.java b/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/api/CloudianSsoLoginCmd.java
new file mode 100644
index 00000000000..7bdd7fda5e1
--- /dev/null
+++ b/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/api/CloudianSsoLoginCmd.java
@@ -0,0 +1,70 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.cloudian.api;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.cloudian.CloudianConnector;
+import org.apache.cloudstack.cloudian.response.CloudianSsoLoginResponse;
+
+import com.cloud.user.Account;
+import com.google.common.base.Strings;
+
+@APICommand(name = CloudianSsoLoginCmd.APINAME, description = "Generates single-sign-on login url for logged-in CloudStack user to access the Cloudian Management Console",
+ responseObject = CloudianSsoLoginResponse.class,
+ since = "4.11.0",
+ authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
+public class CloudianSsoLoginCmd extends BaseCmd {
+ public static final String APINAME = "cloudianSsoLogin";
+
+ @Inject
+ private CloudianConnector connector;
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+
+ @Override
+ public void execute() {
+ final String ssoUrl = connector.generateSsoUrl();
+ if (Strings.isNullOrEmpty(ssoUrl)) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to generate Cloudian single-sign on URL for the user");
+ }
+ final CloudianSsoLoginResponse response = new CloudianSsoLoginResponse();
+ response.setSsoRedirectUrl(ssoUrl);
+ response.setResponseName(getCommandName());
+ response.setObjectName(APINAME.toLowerCase());
+ setResponseObject(response);
+ }
+}
diff --git a/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/client/CloudianClient.java b/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/client/CloudianClient.java
new file mode 100644
index 00000000000..11f2055fef8
--- /dev/null
+++ b/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/client/CloudianClient.java
@@ -0,0 +1,347 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.cloudian.client;
+
+import java.io.IOException;
+import java.net.SocketTimeoutException;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.X509TrustManager;
+
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.utils.security.SSLUtils;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.Credentials;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.AuthCache;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpPut;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.conn.ConnectTimeoutException;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.auth.BasicScheme;
+import org.apache.http.impl.client.BasicAuthCache;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.log4j.Logger;
+
+import com.cloud.utils.nio.TrustAllManager;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Strings;
+
+public class CloudianClient {
+ private static final Logger LOG = Logger.getLogger(CloudianClient.class);
+
+ private final HttpClient httpClient;
+ private final HttpClientContext httpContext;
+ private final String adminApiUrl;
+
+ public CloudianClient(final String host, final Integer port, final String scheme, final String username, final String password, final boolean validateSSlCertificate, final int timeout) throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
+ final CredentialsProvider provider = new BasicCredentialsProvider();
+ provider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
+ final HttpHost adminHost = new HttpHost(host, port, scheme);
+ final AuthCache authCache = new BasicAuthCache();
+ authCache.put(adminHost, new BasicScheme());
+
+ this.adminApiUrl = adminHost.toURI();
+ this.httpContext = HttpClientContext.create();
+ this.httpContext.setCredentialsProvider(provider);
+ this.httpContext.setAuthCache(authCache);
+
+ final RequestConfig config = RequestConfig.custom()
+ .setConnectTimeout(timeout * 1000)
+ .setConnectionRequestTimeout(timeout * 1000)
+ .setSocketTimeout(timeout * 1000)
+ .build();
+
+ if (!validateSSlCertificate) {
+ final SSLContext sslcontext = SSLUtils.getSSLContext();
+ sslcontext.init(null, new X509TrustManager[]{new TrustAllManager()}, new SecureRandom());
+ final SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslcontext, NoopHostnameVerifier.INSTANCE);
+ this.httpClient = HttpClientBuilder.create()
+ .setDefaultCredentialsProvider(provider)
+ .setDefaultRequestConfig(config)
+ .setSSLSocketFactory(factory)
+ .build();
+ } else {
+ this.httpClient = HttpClientBuilder.create()
+ .setDefaultCredentialsProvider(provider)
+ .setDefaultRequestConfig(config)
+ .build();
+ }
+ }
+
+ private void checkAuthFailure(final HttpResponse response) {
+ if (response != null && response.getStatusLine().getStatusCode() == HttpStatus.SC_UNAUTHORIZED) {
+ final Credentials credentials = httpContext.getCredentialsProvider().getCredentials(AuthScope.ANY);
+ LOG.error("Cloudian admin API authentication failed, please check Cloudian configuration. Admin auth principal=" + credentials.getUserPrincipal() + ", password=" + credentials.getPassword() + ", API url=" + adminApiUrl);
+ throw new ServerApiException(ApiErrorCode.UNAUTHORIZED, "Cloudian backend API call unauthorized, please ask your administrator to fix integration issues.");
+ }
+ }
+
+ private void checkResponseOK(final HttpResponse response) {
+ if (response.getStatusLine().getStatusCode() == HttpStatus.SC_NO_CONTENT) {
+ LOG.debug("Requested Cloudian resource does not exist");
+ return;
+ }
+ if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK && response.getStatusLine().getStatusCode() != HttpStatus.SC_NO_CONTENT) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to find the requested resource and get valid response from Cloudian backend API call, please ask your administrator to diagnose and fix issues.");
+ }
+ }
+
+ private boolean checkEmptyResponse(final HttpResponse response) throws IOException {
+ return response != null && (response.getStatusLine().getStatusCode() == HttpStatus.SC_NO_CONTENT ||
+ response.getEntity() == null ||
+ response.getEntity().getContent() == null);
+ }
+
+ private void checkResponseTimeOut(final Exception e) {
+ if (e instanceof ConnectTimeoutException || e instanceof SocketTimeoutException) {
+ throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, "Operation timed out, please try again.");
+ }
+ }
+
+ private HttpResponse delete(final String path) throws IOException {
+ final HttpResponse response = httpClient.execute(new HttpDelete(adminApiUrl + path), httpContext);
+ checkAuthFailure(response);
+ return response;
+ }
+
+ private HttpResponse get(final String path) throws IOException {
+ final HttpResponse response = httpClient.execute(new HttpGet(adminApiUrl + path), httpContext);
+ checkAuthFailure(response);
+ return response;
+ }
+
+ private HttpResponse post(final String path, final Object item) throws IOException {
+ final ObjectMapper mapper = new ObjectMapper();
+ final String json = mapper.writeValueAsString(item);
+ final StringEntity entity = new StringEntity(json);
+ final HttpPost request = new HttpPost(adminApiUrl + path);
+ request.setHeader("Content-type", "application/json");
+ request.setEntity(entity);
+ final HttpResponse response = httpClient.execute(request, httpContext);
+ checkAuthFailure(response);
+ return response;
+ }
+
+ private HttpResponse put(final String path, final Object item) throws IOException {
+ final ObjectMapper mapper = new ObjectMapper();
+ final String json = mapper.writeValueAsString(item);
+ final StringEntity entity = new StringEntity(json);
+ final HttpPut request = new HttpPut(adminApiUrl + path);
+ request.setHeader("Content-type", "application/json");
+ request.setEntity(entity);
+ final HttpResponse response = httpClient.execute(request, httpContext);
+ checkAuthFailure(response);
+ return response;
+ }
+
+ ////////////////////////////////////////////////////////
+ //////////////// Public APIs: User /////////////////////
+ ////////////////////////////////////////////////////////
+
+ public boolean addUser(final CloudianUser user) {
+ if (user == null) {
+ return false;
+ }
+ LOG.debug("Adding Cloudian user: " + user);
+ try {
+ final HttpResponse response = put("/user", user);
+ return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK;
+ } catch (final IOException e) {
+ LOG.error("Failed to add Cloudian user due to:", e);
+ checkResponseTimeOut(e);
+ }
+ return false;
+ }
+
+ public CloudianUser listUser(final String userId, final String groupId) {
+ if (Strings.isNullOrEmpty(userId) || Strings.isNullOrEmpty(groupId)) {
+ return null;
+ }
+ LOG.debug("Trying to find Cloudian user with id=" + userId + " and group id=" + groupId);
+ try {
+ final HttpResponse response = get(String.format("/user?userId=%s&groupId=%s", userId, groupId));
+ checkResponseOK(response);
+ if (checkEmptyResponse(response)) {
+ return null;
+ }
+ final ObjectMapper mapper = new ObjectMapper();
+ return mapper.readValue(response.getEntity().getContent(), CloudianUser.class);
+ } catch (final IOException e) {
+ LOG.error("Failed to list Cloudian user due to:", e);
+ checkResponseTimeOut(e);
+ }
+ return null;
+ }
+
+ public List<CloudianUser> listUsers(final String groupId) {
+ if (Strings.isNullOrEmpty(groupId)) {
+ return new ArrayList<>();
+ }
+ LOG.debug("Trying to list Cloudian users in group id=" + groupId);
+ try {
+ final HttpResponse response = get(String.format("/user/list?groupId=%s&userType=all&userStatus=active", groupId));
+ checkResponseOK(response);
+ if (checkEmptyResponse(response)) {
+ return new ArrayList<>();
+ }
+ final ObjectMapper mapper = new ObjectMapper();
+ return Arrays.asList(mapper.readValue(response.getEntity().getContent(), CloudianUser[].class));
+ } catch (final IOException e) {
+ LOG.error("Failed to list Cloudian users due to:", e);
+ checkResponseTimeOut(e);
+ }
+ return new ArrayList<>();
+ }
+
+ public boolean updateUser(final CloudianUser user) {
+ if (user == null) {
+ return false;
+ }
+ LOG.debug("Updating Cloudian user: " + user);
+ try {
+ final HttpResponse response = post("/user", user);
+ return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK;
+ } catch (final IOException e) {
+ LOG.error("Failed to update Cloudian user due to:", e);
+ checkResponseTimeOut(e);
+ }
+ return false;
+ }
+
+ public boolean removeUser(final String userId, final String groupId) {
+ if (Strings.isNullOrEmpty(userId) || Strings.isNullOrEmpty(groupId)) {
+ return false;
+ }
+ LOG.debug("Removing Cloudian user with user id=" + userId + " in group id=" + groupId);
+ try {
+ final HttpResponse response = delete(String.format("/user?userId=%s&groupId=%s", userId, groupId));
+ return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK;
+ } catch (final IOException e) {
+ LOG.error("Failed to remove Cloudian user due to:", e);
+ checkResponseTimeOut(e);
+ }
+ return false;
+ }
+
+ /////////////////////////////////////////////////////////
+ //////////////// Public APIs: Group /////////////////////
+ /////////////////////////////////////////////////////////
+
+ public boolean addGroup(final CloudianGroup group) {
+ if (group == null) {
+ return false;
+ }
+ LOG.debug("Adding Cloudian group: " + group);
+ try {
+ final HttpResponse response = put("/group", group);
+ return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK;
+ } catch (final IOException e) {
+ LOG.error("Failed to add Cloudian group due to:", e);
+ checkResponseTimeOut(e);
+ }
+ return false;
+ }
+
+ public CloudianGroup listGroup(final String groupId) {
+ if (Strings.isNullOrEmpty(groupId)) {
+ return null;
+ }
+ LOG.debug("Trying to find Cloudian group with id=" + groupId);
+ try {
+ final HttpResponse response = get(String.format("/group?groupId=%s", groupId));
+ checkResponseOK(response);
+ if (checkEmptyResponse(response)) {
+ return null;
+ }
+ final ObjectMapper mapper = new ObjectMapper();
+ return mapper.readValue(response.getEntity().getContent(), CloudianGroup.class);
+ } catch (final IOException e) {
+ LOG.error("Failed to list Cloudian group due to:", e);
+ checkResponseTimeOut(e);
+ }
+ return null;
+ }
+
+ public List<CloudianGroup> listGroups() {
+ LOG.debug("Trying to list Cloudian groups");
+ try {
+ final HttpResponse response = get("/group/list");
+ checkResponseOK(response);
+ if (checkEmptyResponse(response)) {
+ return new ArrayList<>();
+ }
+ final ObjectMapper mapper = new ObjectMapper();
+ return Arrays.asList(mapper.readValue(response.getEntity().getContent(), CloudianGroup[].class));
+ } catch (final IOException e) {
+ LOG.error("Failed to list Cloudian groups due to:", e);
+ checkResponseTimeOut(e);
+ }
+ return new ArrayList<>();
+ }
+
+ public boolean updateGroup(final CloudianGroup group) {
+ if (group == null) {
+ return false;
+ }
+ LOG.debug("Updating Cloudian group: " + group);
+ try {
+ final HttpResponse response = post("/group", group);
+ return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK;
+ } catch (final IOException e) {
+ LOG.error("Failed to remove group due to:", e);
+ checkResponseTimeOut(e);
+ }
+ return false;
+ }
+
+ public boolean removeGroup(final String groupId) {
+ if (Strings.isNullOrEmpty(groupId)) {
+ return false;
+ }
+ LOG.debug("Removing Cloudian group id=" + groupId);
+ try {
+ final HttpResponse response = delete(String.format("/group?groupId=%s", groupId));
+ return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK;
+ } catch (final IOException e) {
+ LOG.error("Failed to remove group due to:", e);
+ checkResponseTimeOut(e);
+ }
+ return false;
+ }
+}
diff --git a/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/client/CloudianGroup.java b/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/client/CloudianGroup.java
new file mode 100644
index 00000000000..0a3c4e475a1
--- /dev/null
+++ b/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/client/CloudianGroup.java
@@ -0,0 +1,56 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.cloudian.client;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class CloudianGroup {
+ String groupId;
+ String groupName;
+ Boolean active;
+
+ @Override
+ public String toString() {
+ return String.format("Cloudian Group [id=%s, name=%s, active=%s]", groupId, groupName, active);
+ }
+
+ public String getGroupId() {
+ return groupId;
+ }
+
+ public void setGroupId(String groupId) {
+ this.groupId = groupId;
+ }
+
+ public String getGroupName() {
+ return groupName;
+ }
+
+ public void setGroupName(String groupName) {
+ this.groupName = groupName;
+ }
+
+ public Boolean getActive() {
+ return active;
+ }
+
+ public void setActive(Boolean active) {
+ this.active = active;
+ }
+}
diff --git a/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/client/CloudianUser.java b/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/client/CloudianUser.java
new file mode 100644
index 00000000000..88d45f90976
--- /dev/null
+++ b/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/client/CloudianUser.java
@@ -0,0 +1,85 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.cloudian.client;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class CloudianUser {
+ public static final String USER = "User";
+
+ String userId;
+ String groupId;
+ String userType;
+ String fullName;
+ String emailAddr;
+ Boolean active;
+
+ @Override
+ public String toString() {
+ return String.format("Cloudian User [id=%s, group id=%s, type=%s, active=%s, name=%s]", userId, groupId, userType, active, fullName);
+ }
+
+ public String getUserId() {
+ return userId;
+ }
+
+ public void setUserId(String userId) {
+ this.userId = userId;
+ }
+
+ public String getGroupId() {
+ return groupId;
+ }
+
+ public void setGroupId(String groupId) {
+ this.groupId = groupId;
+ }
+
+ public String getUserType() {
+ return userType;
+ }
+
+ public void setUserType(String userType) {
+ this.userType = userType;
+ }
+
+ public String getFullName() {
+ return fullName;
+ }
+
+ public void setFullName(String fullName) {
+ this.fullName = fullName;
+ }
+
+ public String getEmailAddr() {
+ return emailAddr;
+ }
+
+ public void setEmailAddr(String emailAddr) {
+ this.emailAddr = emailAddr;
+ }
+
+ public Boolean getActive() {
+ return active;
+ }
+
+ public void setActive(Boolean active) {
+ this.active = active;
+ }
+}
diff --git a/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/client/CloudianUtils.java b/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/client/CloudianUtils.java
new file mode 100644
index 00000000000..faca579886e
--- /dev/null
+++ b/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/client/CloudianUtils.java
@@ -0,0 +1,92 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.cloudian.client;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.log4j.Logger;
+
+import com.cloud.utils.HttpUtils;
+import com.google.common.base.Strings;
+
+public class CloudianUtils {
+
+ private static final Logger LOG = Logger.getLogger(CloudianUtils.class);
+ private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";
+
+ /**
+ * Generates RFC-2104 compliant HMAC signature
+ * @param data
+ * @param key
+ * @return returns the generated signature or null on error
+ */
+ public static String generateHMACSignature(final String data, final String key) {
+ if (Strings. isNullOrEmpty(data) || Strings.isNullOrEmpty(key)) {
+ return null;
+ }
+ try {
+ final SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM);
+ final Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
+ mac.init(signingKey);
+ byte[] rawHmac = mac.doFinal(data.getBytes());
+ return Base64.encodeBase64String(rawHmac);
+ } catch (final Exception e) {
+ LOG.error("Failed to generate HMAC signature from provided data and key, due to: ", e);
+ }
+ return null;
+ }
+
+ /**
+ * Generates URL parameters for single-sign on URL
+ * @param user
+ * @param group
+ * @param ssoKey
+ * @return returns SSO URL parameters or null on error
+ */
+ public static String generateSSOUrl(final String cmcUrlPath, final String user, final String group, final String ssoKey) {
+ final StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.append("user=").append(user);
+ stringBuilder.append("&group=").append(group);
+ stringBuilder.append("×tamp=").append(System.currentTimeMillis());
+
+ final String signature = generateHMACSignature(stringBuilder.toString(), ssoKey);
+ if (Strings.isNullOrEmpty(signature)) {
+ return null;
+ }
+
+ try {
+ stringBuilder.append("&signature=").append(URLEncoder.encode(signature, HttpUtils.UTF_8));
+ } catch (final UnsupportedEncodingException e) {
+ return null;
+ }
+
+ stringBuilder.append("&redirect=");
+ if (group.equals("0")) {
+ stringBuilder.append("admin.htm");
+ } else {
+ stringBuilder.append("explorer.htm");
+ }
+
+ return cmcUrlPath + "ssosecurelogin.htm?" + stringBuilder.toString();
+ }
+}
diff --git a/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/response/CloudianEnabledResponse.java b/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/response/CloudianEnabledResponse.java
new file mode 100644
index 00000000000..49d8cda2eaf
--- /dev/null
+++ b/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/response/CloudianEnabledResponse.java
@@ -0,0 +1,42 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.cloudian.response;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseResponse;
+
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+public class CloudianEnabledResponse extends BaseResponse {
+ @SerializedName(ApiConstants.ENABLED)
+ @Param(description = "the Cloudian connector enabled state")
+ private Boolean enabled;
+
+ @SerializedName(ApiConstants.URL)
+ @Param(description = "the Cloudian Management Console base URL")
+ private String cmcUrl;
+
+ public void setEnabled(Boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public void setCmcUrl(String cmcUrl) {
+ this.cmcUrl = cmcUrl;
+ }
+}
diff --git a/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/response/CloudianSsoLoginResponse.java b/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/response/CloudianSsoLoginResponse.java
new file mode 100644
index 00000000000..1731456e197
--- /dev/null
+++ b/plugins/integrations/cloudian/src/org/apache/cloudstack/cloudian/response/CloudianSsoLoginResponse.java
@@ -0,0 +1,34 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.cloudian.response;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseResponse;
+
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+public class CloudianSsoLoginResponse extends BaseResponse {
+ @SerializedName(ApiConstants.URL)
+ @Param(description = "the sso redirect url")
+ private String ssoRedirectUrl;
+
+ public void setSsoRedirectUrl(final String ssoRedirectUrl) {
+ this.ssoRedirectUrl = ssoRedirectUrl;
+ }
+}
diff --git a/plugins/integrations/cloudian/test/org/apache/cloudstack/cloudian/CloudianClientTest.java b/plugins/integrations/cloudian/test/org/apache/cloudstack/cloudian/CloudianClientTest.java
new file mode 100644
index 00000000000..23ba1e1294b
--- /dev/null
+++ b/plugins/integrations/cloudian/test/org/apache/cloudstack/cloudian/CloudianClientTest.java
@@ -0,0 +1,416 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.cloudian;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.containing;
+import static com.github.tomakehurst.wiremock.client.WireMock.delete;
+import static com.github.tomakehurst.wiremock.client.WireMock.deleteRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.post;
+import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.put;
+import static com.github.tomakehurst.wiremock.client.WireMock.putRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching;
+import static com.github.tomakehurst.wiremock.client.WireMock.verify;
+
+import java.util.List;
+
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.cloudian.client.CloudianClient;
+import org.apache.cloudstack.cloudian.client.CloudianGroup;
+import org.apache.cloudstack.cloudian.client.CloudianUser;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.github.tomakehurst.wiremock.client.BasicCredentials;
+import com.github.tomakehurst.wiremock.junit.WireMockRule;
+
+public class CloudianClientTest {
+ private final int port = 14333;
+ private final int timeout = 2;
+ private final String adminUsername = "admin";
+ private final String adminPassword = "public";
+ private CloudianClient client;
+
+ @Rule
+ public WireMockRule wireMockRule = new WireMockRule(port);
+
+ @Before
+ public void setUp() throws Exception {
+ client = new CloudianClient("localhost", port, "http", adminUsername, adminPassword, false, timeout);
+ }
+
+ private CloudianUser getTestUser() {
+ final CloudianUser user = new CloudianUser();
+ user.setActive(true);
+ user.setUserId("someUserId");
+ user.setGroupId("someGroupId");
+ user.setUserType(CloudianUser.USER);
+ user.setFullName("John Doe");
+ return user;
+ }
+
+ private CloudianGroup getTestGroup() {
+ final CloudianGroup group = new CloudianGroup();
+ group.setActive(true);
+ group.setGroupId("someGroupId");
+ group.setGroupName("someGroupName");
+ return group;
+ }
+
+ ////////////////////////////////////////////////////////
+ //////////////// General API tests /////////////////////
+ ////////////////////////////////////////////////////////
+
+ @Test(expected = CloudRuntimeException.class)
+ public void testRequestTimeout() {
+ wireMockRule.stubFor(get(urlEqualTo("/group/list"))
+ .willReturn(aResponse()
+ .withHeader("Content-Type", "application/json")
+ .withStatus(200)
+ .withFixedDelay(2 * timeout * 1000)
+ .withBody("")));
+ client.listGroups();
+ }
+
+ @Test
+ public void testBasicAuth() {
+ wireMockRule.stubFor(get(urlEqualTo("/group/list"))
+ .willReturn(aResponse()
+ .withStatus(200)
+ .withBody("[]")));
+ client.listGroups();
+ verify(getRequestedFor(urlEqualTo("/group/list"))
+ .withBasicAuth(new BasicCredentials(adminUsername, adminPassword)));
+ }
+
+ @Test(expected = ServerApiException.class)
+ public void testBasicAuthFailure() {
+ wireMockRule.stubFor(get(urlPathMatching("/user"))
+ .willReturn(aResponse()
+ .withStatus(401)
+ .withBody("")));
+ client.listUser("someUserId", "somegGroupId");
+ }
+
+ /////////////////////////////////////////////////////
+ //////////////// User API tests /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Test
+ public void addUserAccount() {
+ wireMockRule.stubFor(put(urlEqualTo("/user"))
+ .willReturn(aResponse()
+ .withStatus(200)
+ .withBody("")));
+
+ final CloudianUser user = getTestUser();
+ boolean result = client.addUser(user);
+ Assert.assertTrue(result);
+ verify(putRequestedFor(urlEqualTo("/user"))
+ .withRequestBody(containing("userId\":\"" + user.getUserId()))
+ .withHeader("Content-Type", equalTo("application/json")));
+ }
+
+ @Test
+ public void addUserAccountFail() {
+ wireMockRule.stubFor(put(urlEqualTo("/user"))
+ .willReturn(aResponse()
+ .withStatus(400)
+ .withBody("")));
+
+ final CloudianUser user = getTestUser();
+ boolean result = client.addUser(user);
+ Assert.assertFalse(result);
+ }
+
+ @Test
+ public void listUserAccount() {
+ final String userId = "someUser";
+ final String groupId = "someGroup";
+ wireMockRule.stubFor(get(urlPathMatching("/user?.*"))
+ .willReturn(aResponse()
+ .withHeader("Content-Type", "application/json")
+ .withBody("{\"userId\":\"someUser\",\"userType\":\"User\",\"fullName\":\"John Doe (jdoe)\",\"emailAddr\":\"j@doe.com\",\"address1\":null,\"address2\":null,\"city\":null,\"state\":null,\"zip\":null,\"country\":null,\"phone\":null,\"groupId\":\"someGroup\",\"website\":null,\"active\":\"true\",\"canonicalUserId\":\"b3940886468689d375ebf8747b151c37\",\"ldapEnabled\":false}")));
+
+ final CloudianUser user = client.listUser(userId, groupId);
+ Assert.assertEquals(user.getActive(), true);
+ Assert.assertEquals(user.getUserId(), userId);
+ Assert.assertEquals(user.getGroupId(), groupId);
+ Assert.assertEquals(user.getUserType(), "User");
+ }
+
+ @Test
+ public void listUserAccountFail() {
+ wireMockRule.stubFor(get(urlPathMatching("/user?.*"))
+ .willReturn(aResponse()
+ .withHeader("Content-Type", "application/json")
+ .withBody("")));
+
+ final CloudianUser user = client.listUser("abc", "xyz");
+ Assert.assertNull(user);
+ }
+
+ @Test
+ public void listUserAccounts() {
+ final String groupId = "someGroup";
+ wireMockRule.stubFor(get(urlPathMatching("/user/list?.*"))
+ .willReturn(aResponse()
+ .withHeader("Content-Type", "application/json")
+ .withBody("[{\"userId\":\"someUser\",\"userType\":\"User\",\"fullName\":\"John Doe (jdoe)\",\"emailAddr\":\"j@doe.com\",\"address1\":null,\"address2\":null,\"city\":null,\"state\":null,\"zip\":null,\"country\":null,\"phone\":null,\"groupId\":\"someGroup\",\"website\":null,\"active\":\"true\",\"canonicalUserId\":\"b3940886468689d375ebf8747b151c37\",\"ldapEnabled\":false}]")));
+
+ final List<CloudianUser> users = client.listUsers(groupId);
+ Assert.assertEquals(users.size(), 1);
+ Assert.assertEquals(users.get(0).getActive(), true);
+ Assert.assertEquals(users.get(0).getGroupId(), groupId);
+ }
+
+ @Test
+ public void testEmptyListUsersResponse() {
+ wireMockRule.stubFor(get(urlPathMatching("/user/list"))
+ .willReturn(aResponse()
+ .withHeader("Content-Type", "application/json")
+ .withStatus(204)
+ .withBody("")));
+ Assert.assertTrue(client.listUsers("someGroup").size() == 0);
+
+ wireMockRule.stubFor(get(urlPathMatching("/user"))
+ .willReturn(aResponse()
+ .withHeader("Content-Type", "application/json")
+ .withStatus(204)
+ .withBody("")));
+ Assert.assertNull(client.listUser("someUserId", "someGroupId"));
+ }
+
+ @Test
+ public void listUserAccountsFail() {
+ wireMockRule.stubFor(get(urlPathMatching("/user/list?.*"))
+ .willReturn(aResponse()
+ .withHeader("Content-Type", "application/json")
+ .withBody("")));
+
+ final List<CloudianUser> users = client.listUsers("xyz");
+ Assert.assertEquals(users.size(), 0);
+ }
+
+ @Test
+ public void updateUserAccount() {
+ wireMockRule.stubFor(post(urlEqualTo("/user"))
+ .willReturn(aResponse()
+ .withStatus(200)
+ .withBody("")));
+
+ final CloudianUser user = getTestUser();
+ boolean result = client.updateUser(user);
+ Assert.assertTrue(result);
+ verify(postRequestedFor(urlEqualTo("/user"))
+ .withRequestBody(containing("userId\":\"" + user.getUserId()))
+ .withHeader("Content-Type", equalTo("application/json")));
+ }
+
+ @Test
+ public void updateUserAccountFail() {
+ wireMockRule.stubFor(post(urlEqualTo("/user"))
+ .willReturn(aResponse()
+ .withStatus(400)
+ .withBody("")));
+
+ boolean result = client.updateUser(getTestUser());
+ Assert.assertFalse(result);
+ }
+
+ @Test
+ public void removeUserAccount() {
+ wireMockRule.stubFor(delete(urlPathMatching("/user.*"))
+ .willReturn(aResponse()
+ .withStatus(200)
+ .withBody("")));
+ final CloudianUser user = getTestUser();
+ boolean result = client.removeUser(user.getUserId(), user.getGroupId());
+ Assert.assertTrue(result);
+ verify(deleteRequestedFor(urlPathMatching("/user.*"))
+ .withQueryParam("userId", equalTo(user.getUserId())));
+ }
+
+ @Test
+ public void removeUserAccountFail() {
+ wireMockRule.stubFor(delete(urlPathMatching("/user.*"))
+ .willReturn(aResponse()
+ .withStatus(400)
+ .withBody("")));
+ final CloudianUser user = getTestUser();
+ boolean result = client.removeUser(user.getUserId(), user.getGroupId());
+ Assert.assertFalse(result);
+ }
+
+ //////////////////////////////////////////////////////
+ //////////////// Group API tests /////////////////////
+ //////////////////////////////////////////////////////
+
+ @Test
+ public void addGroup() {
+ wireMockRule.stubFor(put(urlEqualTo("/group"))
+ .willReturn(aResponse()
+ .withStatus(200)
+ .withBody("")));
+
+ final CloudianGroup group = getTestGroup();
+ boolean result = client.addGroup(group);
+ Assert.assertTrue(result);
+ verify(putRequestedFor(urlEqualTo("/group"))
+ .withRequestBody(containing("groupId\":\"someGroupId"))
+ .withHeader("Content-Type", equalTo("application/json")));
+ }
+
+ @Test
+ public void addGroupFail() throws Exception {
+ wireMockRule.stubFor(put(urlEqualTo("/group"))
+ .willReturn(aResponse()
+ .withStatus(400)
+ .withBody("")));
+
+ final CloudianGroup group = getTestGroup();
+ boolean result = client.addGroup(group);
+ Assert.assertFalse(result);
+ }
+
+ @Test
+ public void listGroup() {
+ final String groupId = "someGroup";
+ wireMockRule.stubFor(get(urlPathMatching("/group.*"))
+ .willReturn(aResponse()
+ .withHeader("Content-Type", "application/json")
+ .withBody("{\"groupId\":\"someGroup\",\"groupName\":\"/someDomain\",\"ldapGroup\":null,\"active\":\"true\",\"ldapEnabled\":false,\"ldapServerURL\":null,\"ldapUserDNTemplate\":null,\"ldapSearch\":null,\"ldapSearchUserBase\":null,\"ldapMatchAttribute\":null}")));
+
+ final CloudianGroup group = client.listGroup(groupId);
+ Assert.assertEquals(group.getActive(), true);
+ Assert.assertEquals(group.getGroupId(), groupId);
+ }
+
+ @Test
+ public void listGroupFail() {
+ wireMockRule.stubFor(get(urlPathMatching("/group.*"))
+ .willReturn(aResponse()
+ .withHeader("Content-Type", "application/json")
+ .withBody("")));
+
+ final CloudianGroup group = client.listGroup("xyz");
+ Assert.assertNull(group);
+ }
+
+ @Test
+ public void listGroups() {
+ final String groupId = "someGroup";
+ wireMockRule.stubFor(get(urlEqualTo("/group/list"))
+ .willReturn(aResponse()
+ .withHeader("Content-Type", "application/json")
+ .withBody("[{\"groupId\":\"someGroup\",\"groupName\":\"/someDomain\",\"ldapGroup\":null,\"active\":\"true\",\"ldapEnabled\":false,\"ldapServerURL\":null,\"ldapUserDNTemplate\":null,\"ldapSearch\":null,\"ldapSearchUserBase\":null,\"ldapMatchAttribute\":null}]")));
+
+ final List<CloudianGroup> groups = client.listGroups();
+ Assert.assertEquals(groups.size(), 1);
+ Assert.assertEquals(groups.get(0).getActive(), true);
+ Assert.assertEquals(groups.get(0).getGroupId(), groupId);
+ }
+
+ @Test
+ public void listGroupsFail() {
+ wireMockRule.stubFor(get(urlEqualTo("/group/list"))
+ .willReturn(aResponse()
+ .withHeader("Content-Type", "application/json")
+ .withBody("")));
+
+ final List<CloudianGroup> groups = client.listGroups();
+ Assert.assertEquals(groups.size(), 0);
+ }
+
+ @Test
+ public void testEmptyListGroupResponse() {
+ wireMockRule.stubFor(get(urlEqualTo("/group/list"))
+ .willReturn(aResponse()
+ .withHeader("Content-Type", "application/json")
+ .withStatus(204)
+ .withBody("")));
+
+ Assert.assertTrue(client.listGroups().size() == 0);
+
+
+ wireMockRule.stubFor(get(urlPathMatching("/group"))
+ .willReturn(aResponse()
+ .withHeader("Content-Type", "application/json")
+ .withStatus(204)
+ .withBody("")));
+ Assert.assertNull(client.listGroup("someGroup"));
+ }
+
+ @Test
+ public void updateGroup() {
+ wireMockRule.stubFor(post(urlEqualTo("/group"))
+ .willReturn(aResponse()
+ .withStatus(200)
+ .withBody("")));
+
+ final CloudianGroup group = getTestGroup();
+ boolean result = client.updateGroup(group);
+ Assert.assertTrue(result);
+ verify(postRequestedFor(urlEqualTo("/group"))
+ .withRequestBody(containing("groupId\":\"" + group.getGroupId()))
+ .withHeader("Content-Type", equalTo("application/json")));
+ }
+
+ @Test
+ public void updateGroupFail() {
+ wireMockRule.stubFor(post(urlEqualTo("/group"))
+ .willReturn(aResponse()
+ .withStatus(400)
+ .withBody("")));
+
+ boolean result = client.updateGroup(getTestGroup());
+ Assert.assertFalse(result);
+ }
+
+ @Test
+ public void removeGroup() {
+ wireMockRule.stubFor(delete(urlPathMatching("/group.*"))
+ .willReturn(aResponse()
+ .withStatus(200)
+ .withBody("")));
+ final CloudianGroup group = getTestGroup();
+ boolean result = client.removeGroup(group.getGroupId());
+ Assert.assertTrue(result);
+ verify(deleteRequestedFor(urlPathMatching("/group.*"))
+ .withQueryParam("groupId", equalTo(group.getGroupId())));
+ }
+
+ @Test
+ public void removeGroupFail() {
+ wireMockRule.stubFor(delete(urlPathMatching("/group.*"))
+ .willReturn(aResponse()
+ .withStatus(400)
+ .withBody("")));
+ final CloudianGroup group = getTestGroup();
+ boolean result = client.removeGroup(group.getGroupId());
+ Assert.assertFalse(result);
+ }
+}
\ No newline at end of file
diff --git a/plugins/integrations/prometheus/pom.xml b/plugins/integrations/prometheus/pom.xml
new file mode 100644
index 00000000000..66dbebbf1d1
--- /dev/null
+++ b/plugins/integrations/prometheus/pom.xml
@@ -0,0 +1,48 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>cloud-plugin-integrations-prometheus-exporter</artifactId>
+ <name>Apache CloudStack Plugin - Prometheus Exporter</name>
+ <parent>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloudstack-plugins</artifactId>
+ <version>4.11.0.0-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-utils</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-engine-schema</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/plugins/network-elements/midonet/resources/META-INF/cloudstack/midonet/module.properties b/plugins/integrations/prometheus/resources/META-INF/cloudstack/prometheus/module.properties
similarity index 96%
rename from plugins/network-elements/midonet/resources/META-INF/cloudstack/midonet/module.properties
rename to plugins/integrations/prometheus/resources/META-INF/cloudstack/prometheus/module.properties
index 786ccc8dbe5..cb70ec81e54 100644
--- a/plugins/network-elements/midonet/resources/META-INF/cloudstack/midonet/module.properties
+++ b/plugins/integrations/prometheus/resources/META-INF/cloudstack/prometheus/module.properties
@@ -14,5 +14,5 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-name=midonet
-parent=network
\ No newline at end of file
+name=prometheus
+parent=api
diff --git a/plugins/integrations/prometheus/resources/META-INF/cloudstack/prometheus/spring-prometheus-context.xml b/plugins/integrations/prometheus/resources/META-INF/cloudstack/prometheus/spring-prometheus-context.xml
new file mode 100644
index 00000000000..06fb92c1617
--- /dev/null
+++ b/plugins/integrations/prometheus/resources/META-INF/cloudstack/prometheus/spring-prometheus-context.xml
@@ -0,0 +1,27 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+ <bean id="prometheusExporterServer" class="org.apache.cloudstack.metrics.PrometheusExporterServerImpl" />
+ <bean id="prometheusExporter" class="org.apache.cloudstack.metrics.PrometheusExporterImpl" />
+
+</beans>
diff --git a/plugins/integrations/prometheus/src/org/apache/cloudstack/metrics/PrometheusExporter.java b/plugins/integrations/prometheus/src/org/apache/cloudstack/metrics/PrometheusExporter.java
new file mode 100644
index 00000000000..6361f0edc6b
--- /dev/null
+++ b/plugins/integrations/prometheus/src/org/apache/cloudstack/metrics/PrometheusExporter.java
@@ -0,0 +1,24 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.metrics;
+
+public interface PrometheusExporter {
+
+ void updateMetrics();
+
+ String getMetrics();
+}
diff --git a/plugins/integrations/prometheus/src/org/apache/cloudstack/metrics/PrometheusExporterImpl.java b/plugins/integrations/prometheus/src/org/apache/cloudstack/metrics/PrometheusExporterImpl.java
new file mode 100644
index 00000000000..a51b2966631
--- /dev/null
+++ b/plugins/integrations/prometheus/src/org/apache/cloudstack/metrics/PrometheusExporterImpl.java
@@ -0,0 +1,612 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.metrics;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
+import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
+import org.apache.log4j.Logger;
+
+import com.cloud.alert.AlertManager;
+import com.cloud.api.ApiDBUtils;
+import com.cloud.api.query.dao.DomainJoinDao;
+import com.cloud.api.query.dao.HostJoinDao;
+import com.cloud.api.query.dao.StoragePoolJoinDao;
+import com.cloud.api.query.vo.DomainJoinVO;
+import com.cloud.api.query.vo.HostJoinVO;
+import com.cloud.api.query.vo.StoragePoolJoinVO;
+import com.cloud.capacity.Capacity;
+import com.cloud.capacity.CapacityManager;
+import com.cloud.capacity.CapacityVO;
+import com.cloud.capacity.dao.CapacityDao;
+import com.cloud.capacity.dao.CapacityDaoImpl;
+import com.cloud.configuration.Resource;
+import com.cloud.dc.DataCenterVO;
+import com.cloud.dc.Vlan;
+import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.dc.dao.DataCenterIpAddressDao;
+import com.cloud.host.Host;
+import com.cloud.host.Status;
+import com.cloud.network.dao.IPAddressDao;
+import com.cloud.storage.ImageStore;
+import com.cloud.storage.StorageStats;
+import com.cloud.storage.Volume;
+import com.cloud.storage.VolumeVO;
+import com.cloud.storage.dao.VolumeDao;
+import com.cloud.utils.component.Manager;
+import com.cloud.utils.component.ManagerBase;
+import com.cloud.vm.VirtualMachine.State;
+import com.cloud.vm.dao.VMInstanceDao;
+import com.google.common.base.Strings;
+
+public class PrometheusExporterImpl extends ManagerBase implements PrometheusExporter, Manager {
+ private static final Logger LOG = Logger.getLogger(PrometheusExporterImpl.class);
+
+ private static final String USED = "used";
+ private static final String ALLOCATED = "allocated";
+ private static final String UNALLOCATED = "unallocated";
+ private static final String TOTAL = "total";
+ private static final String ONLINE = "online";
+ private static final String OFFLINE = "offline";
+
+ private static List<Item> metricsItems = new ArrayList<>();
+
+ @Inject
+ private DataCenterDao dcDao;
+ @Inject
+ private HostJoinDao hostJoinDao;
+ @Inject
+ private VMInstanceDao vmDao;
+ @Inject
+ private VolumeDao volumeDao;
+ @Inject
+ private IPAddressDao publicIpAddressDao;
+ @Inject
+ private DataCenterIpAddressDao privateIpAddressDao;
+ @Inject
+ private CapacityDao capacityDao;
+ @Inject
+ private StoragePoolJoinDao storagePoolJoinDao;
+ @Inject
+ private ImageStoreDao imageStoreDao;
+ @Inject
+ private DomainJoinDao domainDao;
+ @Inject
+ private AlertManager alertManager;
+
+ public PrometheusExporterImpl() {
+ super();
+ }
+
+ private void addHostMetrics(final List<Item> metricsList, final long dcId, final String zoneName, final String zoneUuid) {
+ int total = 0;
+ int up = 0;
+ int down = 0;
+ for (final HostJoinVO host : hostJoinDao.listAll()) {
+ if (host == null || host.getType() != Host.Type.Routing || host.getZoneId() != dcId) {
+ continue;
+ }
+ total++;
+ if (host.getStatus() == Status.Up) {
+ up++;
+ } else if (host.getStatus() == Status.Disconnected || host.getStatus() == Status.Down) {
+ down++;
+ }
+
+ final String cpuFactor = String.valueOf(CapacityManager.CpuOverprovisioningFactor.valueIn(host.getClusterId()));
+ final CapacityVO cpuCapacity = capacityDao.findByHostIdType(host.getId(), Capacity.CAPACITY_TYPE_CPU);
+ metricsList.add(new ItemHostCpu(zoneName, zoneUuid, host.getName(), host.getUuid(), host.getPrivateIpAddress(), cpuFactor, USED, cpuCapacity.getUsedCapacity()));
+ metricsList.add(new ItemHostCpu(zoneName, zoneUuid, host.getName(), host.getUuid(), host.getPrivateIpAddress(), cpuFactor, TOTAL, cpuCapacity.getTotalCapacity()));
+
+ final String memoryFactor = String.valueOf(CapacityManager.MemOverprovisioningFactor.valueIn(host.getClusterId()));
+ final CapacityVO memCapacity = capacityDao.findByHostIdType(host.getId(), Capacity.CAPACITY_TYPE_MEMORY);
+ metricsList.add(new ItemHostMemory(zoneName, zoneUuid, host.getName(), host.getUuid(), host.getPrivateIpAddress(), memoryFactor, USED, memCapacity.getUsedCapacity()));
+ metricsList.add(new ItemHostMemory(zoneName, zoneUuid, host.getName(), host.getUuid(), host.getPrivateIpAddress(), memoryFactor, TOTAL, memCapacity.getTotalCapacity()));
+
+ metricsList.add(new ItemHostVM(zoneName, zoneUuid, host.getName(), host.getUuid(), host.getPrivateIpAddress(), vmDao.listByHostId(host.getId()).size()));
+
+ final CapacityVO coreCapacity = capacityDao.findByHostIdType(host.getId(), Capacity.CAPACITY_TYPE_CPU_CORE);
+ if (coreCapacity != null) {
+ metricsList.add(new ItemVMCore(zoneName, zoneUuid, host.getName(), host.getUuid(), host.getPrivateIpAddress(), USED, coreCapacity.getUsedCapacity()));
+ metricsList.add(new ItemVMCore(zoneName, zoneUuid, host.getName(), host.getUuid(), host.getPrivateIpAddress(), TOTAL, coreCapacity.getTotalCapacity()));
+ }
+ }
+
+ final List<CapacityDaoImpl.SummedCapacity> cpuCapacity = capacityDao.findCapacityBy((int) Capacity.CAPACITY_TYPE_CPU, dcId, null, null);
+ if (cpuCapacity != null && cpuCapacity.size() > 0) {
+ metricsList.add(new ItemHostCpu(zoneName, zoneUuid, null, null, null, null, ALLOCATED, cpuCapacity.get(0).getAllocatedCapacity() != null ? cpuCapacity.get(0).getAllocatedCapacity() : 0));
+ }
+
+ final List<CapacityDaoImpl.SummedCapacity> memCapacity = capacityDao.findCapacityBy((int) Capacity.CAPACITY_TYPE_MEMORY, dcId, null, null);
+ if (memCapacity != null && memCapacity.size() > 0) {
+ metricsList.add(new ItemHostMemory(zoneName, zoneUuid, null, null, null, null, ALLOCATED, memCapacity.get(0).getAllocatedCapacity() != null ? memCapacity.get(0).getAllocatedCapacity() : 0));
+ }
+
+ final List<CapacityDaoImpl.SummedCapacity> coreCapacity = capacityDao.findCapacityBy((int) Capacity.CAPACITY_TYPE_CPU_CORE, dcId, null, null);
+ if (coreCapacity != null && coreCapacity.size() > 0) {
+ metricsList.add(new ItemVMCore(zoneName, zoneUuid, null, null, null, ALLOCATED, coreCapacity.get(0).getAllocatedCapacity() != null ? coreCapacity.get(0).getAllocatedCapacity() : 0));
+ }
+
+ metricsList.add(new ItemHost(zoneName, zoneUuid, ONLINE, up));
+ metricsList.add(new ItemHost(zoneName, zoneUuid, OFFLINE, down));
+ metricsList.add(new ItemHost(zoneName, zoneUuid, TOTAL, total));
+ }
+
+ private void addVMMetrics(final List<Item> metricsList, final long dcId, final String zoneName, final String zoneUuid) {
+ for (final State state : State.values()) {
+ final Long count = vmDao.countByZoneAndState(dcId, state);
+ if (count == null) {
+ continue;
+ }
+ metricsList.add(new ItemVM(zoneName, zoneUuid, state.name().toLowerCase(), count));
+ }
+ }
+
+ private void addVolumeMetrics(final List<Item> metricsList, final long dcId, final String zoneName, final String zoneUuid) {
+ int total = 0;
+ int ready = 0;
+ int destroyed = 0;
+ for (final VolumeVO volume : volumeDao.findByDc(dcId)) {
+ if (volume == null) {
+ continue;
+ }
+ total++;
+ if (volume.getState() == Volume.State.Ready) {
+ ready++;
+ } else if (volume.getState() == Volume.State.Destroy) {
+ destroyed++;
+ }
+ }
+ metricsList.add(new ItemVolume(zoneName, zoneUuid, Volume.State.Ready.name().toLowerCase(), ready));
+ metricsList.add(new ItemVolume(zoneName, zoneUuid, Volume.State.Destroy.name().toLowerCase(), destroyed));
+ metricsList.add(new ItemVolume(zoneName, zoneUuid, TOTAL, total));
+ }
+
+ private void addStorageMetrics(final List<Item> metricsList, final long dcId, final String zoneName, final String zoneUuid) {
+ for (final StoragePoolJoinVO pool: storagePoolJoinDao.listAll()) {
+ if (pool == null || pool.getZoneId() != dcId) {
+ continue;
+ }
+ final String poolName = pool.getName();
+ final String poolPath = pool.getHostAddress() + ":" + pool.getPath();
+
+ long usedCapacity = 0L;
+ long allocatedCapacity = pool.getUsedCapacity() + pool.getReservedCapacity();
+ final long totalCapacity = pool.getCapacityBytes();
+
+ final StorageStats stats = ApiDBUtils.getStoragePoolStatistics(pool.getId());
+ if (stats != null) {
+ usedCapacity = stats.getByteUsed();
+ }
+
+ final BigDecimal poolOverProvisioningFactor = BigDecimal.valueOf(CapacityManager.StorageOverprovisioningFactor.valueIn(pool.getId()));
+ final String poolFactor = poolOverProvisioningFactor.toString();
+
+ metricsList.add(new ItemPool(zoneName, zoneUuid, poolName, poolPath, "primary", poolFactor, USED, usedCapacity));
+ metricsList.add(new ItemPool(zoneName, zoneUuid, poolName, poolPath, "primary", poolFactor, ALLOCATED, allocatedCapacity));
+ metricsList.add(new ItemPool(zoneName, zoneUuid, poolName, poolPath, "primary", poolFactor, UNALLOCATED, poolOverProvisioningFactor.multiply(BigDecimal.valueOf(totalCapacity)).longValue() - allocatedCapacity));
+ metricsList.add(new ItemPool(zoneName, zoneUuid, poolName, poolPath, "primary", poolFactor, TOTAL, totalCapacity));
+ }
+
+ for (final ImageStore imageStore : imageStoreDao.findByScope(new ZoneScope(dcId))) {
+ final StorageStats stats = ApiDBUtils.getSecondaryStorageStatistics(imageStore.getId());
+ metricsList.add(new ItemPool(zoneName, zoneUuid, imageStore.getName(), imageStore.getUrl(), "secondary", null, USED, stats != null ? stats.getByteUsed() : 0));
+ metricsList.add(new ItemPool(zoneName, zoneUuid, imageStore.getName(), imageStore.getUrl(), "secondary", null, TOTAL, stats != null ? stats.getCapacityBytes() : 0));
+ }
+ }
+
+ private void addIpAddressMetrics(final List<Item> metricsList, final long dcId, final String zoneName, final String zoneUuid) {
+ metricsList.add(new ItemPrivateIp(zoneName, zoneUuid, ALLOCATED, privateIpAddressDao.countIPs(dcId, true)));
+ metricsList.add(new ItemPrivateIp(zoneName, zoneUuid, TOTAL, privateIpAddressDao.countIPs(dcId, false)));
+ metricsList.add(new ItemPublicIp(zoneName, zoneUuid, ALLOCATED, publicIpAddressDao.countIPsForNetwork(dcId, true, Vlan.VlanType.VirtualNetwork)));
+ metricsList.add(new ItemPublicIp(zoneName, zoneUuid, TOTAL, publicIpAddressDao.countIPsForNetwork(dcId, false, Vlan.VlanType.VirtualNetwork)));
+ metricsList.add(new ItemSharedNetworkIp(zoneName, zoneUuid, ALLOCATED, publicIpAddressDao.countIPsForNetwork(dcId, true, Vlan.VlanType.DirectAttached)));
+ metricsList.add(new ItemSharedNetworkIp(zoneName, zoneUuid, TOTAL, publicIpAddressDao.countIPsForNetwork(dcId, false, Vlan.VlanType.DirectAttached)));
+ }
+
+ private void addVlanMetrics(final List<Item> metricsList, final long dcId, final String zoneName, final String zoneUuid) {
+ metricsList.add(new ItemVlan(zoneName, zoneUuid, ALLOCATED, dcDao.countZoneVlans(dcId, true)));
+ metricsList.add(new ItemVlan(zoneName, zoneUuid, TOTAL, dcDao.countZoneVlans(dcId, false)));
+ }
+
+ private void addDomainLimits(final List<Item> metricsList) {
+ Long totalCpuLimit = 0L;
+ Long totalMemoryLimit = 0L;
+
+ for (final DomainJoinVO domain: domainDao.listAll()) {
+ if (domain == null || domain.getLevel() != 1) {
+ continue;
+ }
+ long cpuLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getCpuLimit(), false,
+ Resource.ResourceType.cpu, domain.getId());
+ if (cpuLimit > 0) {
+ totalCpuLimit += cpuLimit;
+ }
+
+ long memoryLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getMemoryLimit(), false,
+ Resource.ResourceType.memory, domain.getId());
+ if (memoryLimit > 0) {
+ totalMemoryLimit += memoryLimit;
+ }
+ }
+ metricsList.add(new ItemDomainLimitCpu(totalCpuLimit));
+ metricsList.add(new ItemDomainLimitMemory(totalMemoryLimit));
+ }
+
+ @Override
+ public void updateMetrics() {
+ final List<Item> latestMetricsItems = new ArrayList<Item>();
+ try {
+ for (final DataCenterVO dc : dcDao.listAll()) {
+ final String zoneName = dc.getName();
+ final String zoneUuid = dc.getUuid();
+ alertManager.recalculateCapacity();
+ addHostMetrics(latestMetricsItems, dc.getId(), zoneName, zoneUuid);
+ addVMMetrics(latestMetricsItems, dc.getId(), zoneName, zoneUuid);
+ addVolumeMetrics(latestMetricsItems, dc.getId(), zoneName, zoneUuid);
+ addStorageMetrics(latestMetricsItems, dc.getId(), zoneName, zoneUuid);
+ addIpAddressMetrics(latestMetricsItems, dc.getId(), zoneName, zoneUuid);
+ addVlanMetrics(latestMetricsItems, dc.getId(), zoneName, zoneUuid);
+ }
+ addDomainLimits(latestMetricsItems);
+ } catch (Exception e) {
+ LOG.warn("Getting metrics failed ", e);
+ }
+ metricsItems = latestMetricsItems;
+ }
+
+ @Override
+ public String getMetrics() {
+ final StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.append("# Cloudstack Prometheus Metrics\n");
+ for (final Item item : metricsItems) {
+ stringBuilder.append(item.toMetricsString()).append("\n");
+ }
+ return stringBuilder.toString();
+ }
+
+ private abstract class Item {
+ String name;
+
+ public Item(final String nm) {
+ name = nm;
+ }
+
+ public abstract String toMetricsString();
+ }
+
+ class ItemVM extends Item {
+ String zoneName;
+ String zoneUuid;
+ String filter;
+ long total;
+
+ public ItemVM(final String zn, final String zu, final String st, long cnt) {
+ super("cloudstack_vms_total");
+ zoneName = zn;
+ zoneUuid = zu;
+ filter = st;
+ total = cnt;
+ }
+
+ @Override
+ public String toMetricsString() {
+ return String.format("%s{zone=\"%s\",filter=\"%s\"} %d", name, zoneName, filter, total);
+ }
+ }
+
+ class ItemVolume extends Item {
+ String zoneName;
+ String zoneUuid;
+ String filter;
+ int total;
+
+ public ItemVolume(final String zn, final String zu, final String st, int cnt) {
+ super("cloudstack_volumes_total");
+ zoneName = zn;
+ zoneUuid = zu;
+ filter = st;
+ total = cnt;
+ }
+
+ @Override
+ public String toMetricsString() {
+ return String.format("%s{zone=\"%s\",filter=\"%s\"} %d", name, zoneName, filter, total);
+ }
+ }
+
+ class ItemHost extends Item {
+ String zoneName;
+ String zoneUuid;
+ String state;
+ int total;
+
+ public ItemHost(final String zn, final String zu, final String st, int cnt) {
+ super("cloudstack_hosts_total");
+ zoneName = zn;
+ zoneUuid = zu;
+ state = st;
+ total = cnt;
+ }
+
+ @Override
+ public String toMetricsString() {
+ return String.format("%s{zone=\"%s\",filter=\"%s\"} %d", name, zoneName, state, total);
+ }
+ }
+
+ class ItemVMCore extends Item {
+ String zoneName;
+ String zoneUuid;
+ String hostName;
+ String uuid;
+ String ip;
+ String filter;
+ long core = 0;
+
+ public ItemVMCore(final String zn, final String zu, final String hn, final String hu, final String hip, final String fl, final Long cr) {
+ super("cloudstack_host_vms_cores_total");
+ zoneName = zn;
+ zoneUuid = zu;
+ hostName = hn;
+ uuid = hu;
+ ip = hip;
+ filter = fl;
+ if (cr != null) {
+ core = cr;
+ }
+ }
+
+ @Override
+ public String toMetricsString() {
+ if (Strings.isNullOrEmpty(hostName) && Strings.isNullOrEmpty(ip)) {
+ return String.format("%s{zone=\"%s\",filter=\"%s\"} %d", name, zoneName, filter, core);
+ }
+ return String.format("%s{zone=\"%s\",hostname=\"%s\",ip=\"%s\",filter=\"%s\"} %d", name, zoneName, hostName, ip, filter, core);
+ }
+ }
+
+ class ItemHostCpu extends Item {
+ String zoneName;
+ String zoneUuid;
+ String hostName;
+ String uuid;
+ String ip;
+ String overProvisioningFactor;
+ String filter;
+ double mhertz;
+
+ public ItemHostCpu(final String zn, final String zu, final String hn, final String hu, final String hip, final String of, final String fl, final double mh) {
+ super("cloudstack_host_cpu_usage_mhz_total");
+ zoneName = zn;
+ zoneUuid = zu;
+ hostName = hn;
+ uuid = hu;
+ ip = hip;
+ overProvisioningFactor = of;
+ filter = fl;
+ mhertz = mh;
+ }
+
+ @Override
+ public String toMetricsString() {
+ if (Strings.isNullOrEmpty(hostName) && Strings.isNullOrEmpty(ip)) {
+ return String.format("%s{zone=\"%s\",filter=\"%s\"} %.2f", name, zoneName, filter, mhertz);
+ }
+ return String.format("%s{zone=\"%s\",hostname=\"%s\",ip=\"%s\",overprovisioningfactor=\"%s\",filter=\"%s\"} %.2f", name, zoneName, hostName, ip, overProvisioningFactor, filter, mhertz);
+ }
+ }
+
+ class ItemHostMemory extends Item {
+ String zoneName;
+ String zoneUuid;
+ String hostName;
+ String uuid;
+ String ip;
+ String overProvisioningFactor;
+ String filter;
+ double miBytes;
+
+ public ItemHostMemory(final String zn, final String zu, final String hn, final String hu, final String hip, final String of, final String fl, final double membytes) {
+ super("cloudstack_host_memory_usage_mibs_total");
+ zoneName = zn;
+ zoneUuid = zu;
+ hostName = hn;
+ uuid = hu;
+ ip = hip;
+ overProvisioningFactor = of;
+ filter = fl;
+ miBytes = membytes / (1024.0 * 1024.0);
+ }
+
+ @Override
+ public String toMetricsString() {
+ if (Strings.isNullOrEmpty(hostName) && Strings.isNullOrEmpty(ip)) {
+ return String.format("%s{zone=\"%s\",filter=\"%s\"} %.2f", name, zoneName, filter, miBytes);
+ }
+ return String.format("%s{zone=\"%s\",hostname=\"%s\",ip=\"%s\",overprovisioningfactor=\"%s\",filter=\"%s\"} %.2f", name, zoneName, hostName, ip, overProvisioningFactor, filter, miBytes);
+ }
+ }
+
+ class ItemHostVM extends Item {
+ String zoneName;
+ String zoneUuid;
+ String hostName;
+ String hostUuid;
+ String hostIp;
+ int total;
+
+ public ItemHostVM(final String zoneName, final String zoneUuid, final String hostName, final String hostUuid, final String hostIp, final int total) {
+ super("cloudstack_host_vms_total");
+ this.zoneName = zoneName;
+ this.zoneUuid = zoneUuid;
+ this.hostName = hostName;
+ this.hostUuid = hostUuid;
+ this.hostIp = hostIp;
+ this.total = total;
+ }
+
+ @Override
+ public String toMetricsString() {
+ return String.format("%s{zone=\"%s\",hostname=\"%s\",address=\"%s\"} %d", name, zoneName, hostName, hostIp, total);
+ }
+ }
+
+ class ItemPool extends Item {
+ String zoneName;
+ String zoneUuid;
+ String type;
+ String overProvisioningFactor;
+ String filter;
+ String pname;
+ String address;
+ double total;
+
+ public ItemPool(final String zn, final String zu, final String pn, final String pa, final String typ, final String of, final String fl, double cnt) {
+ super("cloudstack_storage_pool_gibs_total");
+ zoneName = zn;
+ zoneUuid = zu;
+ pname = pn;
+ address = pa;
+ type = typ;
+ overProvisioningFactor = of;
+ filter = fl;
+ total = cnt / (1024.0 * 1024.0 * 1024.0);
+ }
+
+ @Override
+ public String toMetricsString() {
+ if (Strings.isNullOrEmpty(overProvisioningFactor)) {
+ return String.format("%s{zone=\"%s\",name=\"%s\",address=\"%s\",type=\"%s\",filter=\"%s\"} %.2f", name, zoneName, pname, address, type, filter, total);
+ }
+ return String.format("%s{zone=\"%s\",name=\"%s\",address=\"%s\",type=\"%s\",overprovisioningfactor=\"%s\",filter=\"%s\"} %.2f", name, zoneName, pname, address, type, overProvisioningFactor, filter, total);
+ }
+ }
+
+ class ItemPrivateIp extends Item {
+ String zoneName;
+ String zoneUuid;
+ String filter;
+ int total;
+
+ public ItemPrivateIp(final String zn, final String zu, final String fl, int cnt) {
+ super("cloudstack_private_ips_total");
+ zoneName = zn;
+ zoneUuid = zu;
+ filter = fl;
+ total = cnt;
+ }
+
+ @Override
+ public String toMetricsString() {
+ return String.format("%s{zone=\"%s\",filter=\"%s\"} %d", name, zoneName, filter, total);
+ }
+ }
+
+ class ItemPublicIp extends Item {
+ String zoneName;
+ String zoneUuid;
+ String filter;
+ int total;
+
+ public ItemPublicIp(final String zn, final String zu, final String fl, int cnt) {
+ super("cloudstack_public_ips_total");
+ zoneName = zn;
+ zoneUuid = zu;
+ filter = fl;
+ total = cnt;
+ }
+
+ @Override
+ public String toMetricsString() {
+ return String.format("%s{zone=\"%s\",filter=\"%s\"} %d", name, zoneName, filter, total);
+ }
+ }
+
+ class ItemSharedNetworkIp extends Item {
+ String zoneName;
+ String zoneUuid;
+ String filter;
+ int total;
+
+ public ItemSharedNetworkIp(final String zn, final String zu, final String fl, int cnt) {
+ super("cloudstack_shared_network_ips_total");
+ zoneName = zn;
+ zoneUuid = zu;
+ filter = fl;
+ total = cnt;
+ }
+
+ @Override
+ public String toMetricsString() {
+ return String.format("%s{zone=\"%s\",filter=\"%s\"} %d", name, zoneName, filter, total);
+ }
+ }
+
+ class ItemVlan extends Item {
+ String zoneName;
+ String zoneUuid;
+ String filter;
+ int total;
+
+ public ItemVlan(final String zn, final String zu, final String fl, int cnt) {
+ super("cloudstack_vlans_total");
+ zoneName = zn;
+ zoneUuid = zu;
+ filter = fl;
+ total = cnt;
+ }
+
+ @Override
+ public String toMetricsString() {
+ return String.format("%s{zone=\"%s\",filter=\"%s\"} %d", name, zoneName, filter, total);
+ }
+ }
+
+ class ItemDomainLimitCpu extends Item {
+ long cores;
+
+ public ItemDomainLimitCpu(final long c) {
+ super("cloudstack_domain_limit_cpu_cores_total");
+ cores = c;
+ }
+
+ @Override
+ public String toMetricsString() {
+ return String.format("%s %d", name, cores);
+ }
+ }
+
+ class ItemDomainLimitMemory extends Item {
+ long miBytes;
+
+ public ItemDomainLimitMemory(final long mb) {
+ super("cloudstack_domain_limit_memory_mibs_total");
+ miBytes = mb;
+ }
+
+ @Override
+ public String toMetricsString() {
+ return String.format("%s %d", name, miBytes);
+ }
+ }
+}
diff --git a/plugins/integrations/prometheus/src/org/apache/cloudstack/metrics/PrometheusExporterServer.java b/plugins/integrations/prometheus/src/org/apache/cloudstack/metrics/PrometheusExporterServer.java
new file mode 100644
index 00000000000..e0303524235
--- /dev/null
+++ b/plugins/integrations/prometheus/src/org/apache/cloudstack/metrics/PrometheusExporterServer.java
@@ -0,0 +1,33 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.metrics;
+
+import org.apache.cloudstack.framework.config.ConfigKey;
+
+import com.cloud.utils.component.Manager;
+
+public interface PrometheusExporterServer extends Manager {
+
+ ConfigKey<Boolean> EnablePrometheusExporter = new ConfigKey<>("Advanced", Boolean.class, "prometheus.exporter.enable", "false",
+ "Enable the prometheus exporter plugin, management server restart needed.", true);
+
+ ConfigKey<Integer> PrometheusExporterServerPort = new ConfigKey<>("Advanced", Integer.class, "prometheus.exporter.port", "9595",
+ "The prometheus exporter server port", true);
+
+ ConfigKey<String> PrometheusExporterAllowedAddresses = new ConfigKey<>("Advanced", String.class, "prometheus.exporter.allowed.ips", "127.0.0.1",
+ "List of comma separated prometheus server ips (with no spaces) that should be allowed to access the URLs", true);
+}
diff --git a/plugins/integrations/prometheus/src/org/apache/cloudstack/metrics/PrometheusExporterServerImpl.java b/plugins/integrations/prometheus/src/org/apache/cloudstack/metrics/PrometheusExporterServerImpl.java
new file mode 100644
index 00000000000..a615c65766b
--- /dev/null
+++ b/plugins/integrations/prometheus/src/org/apache/cloudstack/metrics/PrometheusExporterServerImpl.java
@@ -0,0 +1,118 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.metrics;
+
+import com.cloud.utils.component.ManagerBase;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpServer;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.Configurable;
+import org.apache.log4j.Logger;
+
+import javax.inject.Inject;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.util.Arrays;
+
+public class PrometheusExporterServerImpl extends ManagerBase implements PrometheusExporterServer, Configurable {
+ private static final Logger LOG = Logger.getLogger(PrometheusExporterServerImpl.class);
+
+ private static HttpServer httpServer;
+
+ @Inject
+ private PrometheusExporter prometheusExporter;
+
+ private final static class ExporterHandler implements HttpHandler {
+ private PrometheusExporter prometheusExporter;
+
+ ExporterHandler(final PrometheusExporter prometheusExporter) {
+ super();
+ this.prometheusExporter = prometheusExporter;
+ }
+
+ @Override
+ public void handle(final HttpExchange httpExchange) throws IOException {
+ final String remoteClientAddress = httpExchange.getRemoteAddress().getAddress().toString().replace("/", "");
+ LOG.debug("Prometheus exporter received client request from: " + remoteClientAddress);
+ String response = "Forbidden";
+ int responseCode = 403;
+ if (Arrays.asList(PrometheusExporterAllowedAddresses.value().split(",")).contains(remoteClientAddress)) {
+ prometheusExporter.updateMetrics();
+ response = prometheusExporter.getMetrics();
+ responseCode = 200;
+ }
+ httpExchange.getResponseHeaders().set("Content-Type", "text/plain");
+ httpExchange.sendResponseHeaders(responseCode, response.length());
+ final OutputStream os = httpExchange.getResponseBody();
+ os.write(response.getBytes());
+ os.close();
+ }
+ }
+
+ @Override
+ public boolean start() {
+ if (EnablePrometheusExporter.value()) {
+ try {
+ httpServer = HttpServer.create(new InetSocketAddress(PrometheusExporterServerPort.value()), 0);
+ httpServer.createContext("/metrics", new ExporterHandler(prometheusExporter));
+ httpServer.createContext("/", new HttpHandler() {
+ @Override
+ public void handle(HttpExchange httpExchange) throws IOException {
+ final String response = "<html><head><title>CloudStack Exporter</title></head>" +
+ "<body><h1>CloudStack Exporter</h1>" +
+ "<p><a href=\"/metrics\">Metrics</a></p>" +
+ "</body></html>";
+ httpExchange.sendResponseHeaders(200, response.length());
+ final OutputStream os = httpExchange.getResponseBody();
+ os.write(response.getBytes());
+ os.close();
+ }
+ });
+ httpServer.start();
+ LOG.debug("Started prometheus exporter http server");
+ } catch (final IOException e) {
+ LOG.info("Failed to start prometheus exporter http server due to: ", e);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean stop() {
+ if (httpServer != null) {
+ httpServer.stop(0);
+ LOG.debug("Stopped Prometheus exporter http server");
+ }
+ return true;
+ }
+
+ @Override
+ public String getConfigComponentName() {
+ return PrometheusExporter.class.getSimpleName();
+ }
+
+ @Override
+ public ConfigKey<?>[] getConfigKeys() {
+ return new ConfigKey<?>[] {
+ EnablePrometheusExporter,
+ PrometheusExporterServerPort,
+ PrometheusExporterAllowedAddresses
+ };
+ }
+}
diff --git a/plugins/metrics/pom.xml b/plugins/metrics/pom.xml
index a65f88fd369..c2a9f95a575 100644
--- a/plugins/metrics/pom.xml
+++ b/plugins/metrics/pom.xml
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/network-elements/bigswitch/pom.xml b/plugins/network-elements/bigswitch/pom.xml
index 2e8000138d2..a06f012753b 100644
--- a/plugins/network-elements/bigswitch/pom.xml
+++ b/plugins/network-elements/bigswitch/pom.xml
@@ -25,7 +25,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<build>
diff --git a/plugins/network-elements/bigswitch/src/com/cloud/network/guru/BigSwitchBcfGuestNetworkGuru.java b/plugins/network-elements/bigswitch/src/com/cloud/network/guru/BigSwitchBcfGuestNetworkGuru.java
index f27a4295590..29a29a46bf8 100644
--- a/plugins/network-elements/bigswitch/src/com/cloud/network/guru/BigSwitchBcfGuestNetworkGuru.java
+++ b/plugins/network-elements/bigswitch/src/com/cloud/network/guru/BigSwitchBcfGuestNetworkGuru.java
@@ -129,7 +129,7 @@
public BigSwitchBcfGuestNetworkGuru() {
super();
- _isolationMethods = new IsolationMethod[] {IsolationMethod.BCF_SEGMENT};
+ _isolationMethods = new IsolationMethod[] {new IsolationMethod("BCF_SEGMENT")};
}
@Override
diff --git a/plugins/network-elements/brocade-vcs/pom.xml b/plugins/network-elements/brocade-vcs/pom.xml
index bb737cd1870..af5ee2d3f07 100644
--- a/plugins/network-elements/brocade-vcs/pom.xml
+++ b/plugins/network-elements/brocade-vcs/pom.xml
@@ -16,7 +16,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/plugins/network-elements/brocade-vcs/src/com/cloud/network/guru/BrocadeVcsGuestNetworkGuru.java b/plugins/network-elements/brocade-vcs/src/com/cloud/network/guru/BrocadeVcsGuestNetworkGuru.java
index ba06d14a4c0..6a201cf988b 100644
--- a/plugins/network-elements/brocade-vcs/src/com/cloud/network/guru/BrocadeVcsGuestNetworkGuru.java
+++ b/plugins/network-elements/brocade-vcs/src/com/cloud/network/guru/BrocadeVcsGuestNetworkGuru.java
@@ -16,11 +16,6 @@
// under the License.
package com.cloud.network.guru;
-import java.util.List;
-
-import javax.inject.Inject;
-
-import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.AssociateMacToNetworkAnswer;
@@ -61,6 +56,10 @@
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachineProfile;
+import org.apache.log4j.Logger;
+
+import javax.inject.Inject;
+import java.util.List;
public class BrocadeVcsGuestNetworkGuru extends GuestNetworkGuru {
private static final Logger s_logger = Logger.getLogger(BrocadeVcsGuestNetworkGuru.class);
@@ -82,7 +81,7 @@
public BrocadeVcsGuestNetworkGuru() {
super();
- _isolationMethods = new IsolationMethod[] {IsolationMethod.VCS};
+ _isolationMethods = new IsolationMethod[] {new IsolationMethod("VCS")};
}
@Override
diff --git a/plugins/network-elements/cisco-vnmc/pom.xml b/plugins/network-elements/cisco-vnmc/pom.xml
index 9fdf36d8e2c..0d2ded3a32b 100644
--- a/plugins/network-elements/cisco-vnmc/pom.xml
+++ b/plugins/network-elements/cisco-vnmc/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/network-elements/dns-notifier/pom.xml b/plugins/network-elements/dns-notifier/pom.xml
index 92fd326f118..85463996a39 100644
--- a/plugins/network-elements/dns-notifier/pom.xml
+++ b/plugins/network-elements/dns-notifier/pom.xml
@@ -22,7 +22,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>cloud-plugin-example-dns-notifier</artifactId>
diff --git a/plugins/network-elements/elastic-loadbalancer/pom.xml b/plugins/network-elements/elastic-loadbalancer/pom.xml
index 577f60d58b6..7f0d203df76 100644
--- a/plugins/network-elements/elastic-loadbalancer/pom.xml
+++ b/plugins/network-elements/elastic-loadbalancer/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
</project>
diff --git a/plugins/network-elements/f5/pom.xml b/plugins/network-elements/f5/pom.xml
index 8b6c84b4e51..fc6b03a6115 100644
--- a/plugins/network-elements/f5/pom.xml
+++ b/plugins/network-elements/f5/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/network-elements/globodns/pom.xml b/plugins/network-elements/globodns/pom.xml
index c783edf0bb5..33cf20fbf52 100644
--- a/plugins/network-elements/globodns/pom.xml
+++ b/plugins/network-elements/globodns/pom.xml
@@ -24,14 +24,14 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>com.globo.globodns</groupId>
<artifactId>globodns-client</artifactId>
- <version>0.0.22</version>
+ <version>0.0.23</version>
</dependency>
</dependencies>
</project>
diff --git a/plugins/network-elements/globodns/test/resources/db.properties b/plugins/network-elements/globodns/test/resources/db.properties
index 6e38a4a6f32..f62d76dd7ae 100644
--- a/plugins/network-elements/globodns/test/resources/db.properties
+++ b/plugins/network-elements/globodns/test/resources/db.properties
@@ -17,7 +17,7 @@
# management server clustering parameters, change cluster.node.IP to the machine IP address
-# in which the management server(Tomcat) is running
+# in which the management server is running
cluster.node.IP=127.0.0.1
cluster.servlet.port=9090
region.id=1
diff --git a/plugins/network-elements/internal-loadbalancer/pom.xml b/plugins/network-elements/internal-loadbalancer/pom.xml
index 257ceffd8ed..36d456e4ca8 100644
--- a/plugins/network-elements/internal-loadbalancer/pom.xml
+++ b/plugins/network-elements/internal-loadbalancer/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<build>
diff --git a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/element/InternalLoadBalancerElement.java b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/element/InternalLoadBalancerElement.java
index 07c5a2dfcaa..3e522f6be4f 100644
--- a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/element/InternalLoadBalancerElement.java
+++ b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/element/InternalLoadBalancerElement.java
@@ -26,6 +26,8 @@
import javax.inject.Inject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.command.admin.internallb.ConfigureInternalLoadBalancerElementCmd;
@@ -81,6 +83,7 @@
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.DomainRouterDao;
+import com.cloud.network.router.NetworkHelper;
public class InternalLoadBalancerElement extends AdapterBase implements LoadBalancingServiceProvider, InternalLoadBalancerElementService, IpDeployer {
private static final Logger s_logger = Logger.getLogger(InternalLoadBalancerElement.class);
@@ -107,6 +110,9 @@
ApplicationLoadBalancerRuleDao _appLbDao;
@Inject
EntityManager _entityMgr;
+ @Autowired
+ @Qualifier("networkHelper")
+ protected NetworkHelper _networkHelper;
protected InternalLoadBalancerElement() {
}
@@ -413,7 +419,7 @@ public boolean validateLBRule(Network network, LoadBalancingRule rule) {
if (routers == null || routers.isEmpty()) {
return true;
}
- return VirtualRouterElement.validateHAProxyLBRule(rule);
+ return _networkHelper.validateHAProxyLBRule(rule);
}
return true;
}
diff --git a/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbelement/ElementChildTestConfiguration.java b/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbelement/ElementChildTestConfiguration.java
index 212dd94b3aa..c233f12c3d5 100644
--- a/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbelement/ElementChildTestConfiguration.java
+++ b/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbelement/ElementChildTestConfiguration.java
@@ -44,6 +44,7 @@
import com.cloud.utils.db.EntityManager;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.dao.DomainRouterDao;
+import com.cloud.network.router.NetworkHelper;
@Configuration
@ComponentScan(basePackageClasses = {NetUtils.class},
@@ -61,6 +62,11 @@ public DomainRouterDao domainRouterDao() {
return Mockito.mock(DomainRouterDao.class);
}
+ @Bean
+ public NetworkHelper networkHelper() {
+ return Mockito.mock(NetworkHelper.class);
+ }
+
@Bean
public VirtualRouterProviderDao virtualRouterProviderDao() {
return Mockito.mock(VirtualRouterProviderDao.class);
diff --git a/plugins/network-elements/juniper-contrail/pom.xml b/plugins/network-elements/juniper-contrail/pom.xml
index 4e0b810d115..f98b629c52c 100644
--- a/plugins/network-elements/juniper-contrail/pom.xml
+++ b/plugins/network-elements/juniper-contrail/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<repositories>
@@ -98,6 +98,12 @@
<version>${project.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-security</artifactId>
+ <version>${cs.jetty.version}</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
diff --git a/plugins/network-elements/juniper-srx/pom.xml b/plugins/network-elements/juniper-srx/pom.xml
index ebe9d0e1d05..d541ea9f621 100644
--- a/plugins/network-elements/juniper-srx/pom.xml
+++ b/plugins/network-elements/juniper-srx/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/network-elements/juniper-srx/src/com/cloud/network/resource/JuniperSrxResource.java b/plugins/network-elements/juniper-srx/src/com/cloud/network/resource/JuniperSrxResource.java
index d60ccb67240..75c7583fe80 100644
--- a/plugins/network-elements/juniper-srx/src/com/cloud/network/resource/JuniperSrxResource.java
+++ b/plugins/network-elements/juniper-srx/src/com/cloud/network/resource/JuniperSrxResource.java
@@ -2841,8 +2841,8 @@ private boolean manageSecurityPolicy(SecurityPolicyType type, SrxCommand command
action = "<permit></permit>";
}
- xml = replaceXmlValue(xml, "action", action);
}
+ xml = replaceXmlValue(xml, "action", action);
} else {
xml = replaceXmlValue(xml, "from-zone", fromZone);
xml = replaceXmlValue(xml, "to-zone", toZone);
@@ -3611,7 +3611,7 @@ private String setDelete(String xml, boolean delete) {
private Long getVlanTag(String vlan) throws ExecutionException {
Long publicVlanTag = null;
- if (!vlan.equals("untagged")) {
+ if (!vlan.contains("untagged")) {
try {
// make sure this vlan is numeric
publicVlanTag = Long.parseLong(BroadcastDomainType.getValue(vlan));
diff --git a/plugins/network-elements/midonet/src/com/cloud/network/element/MidoNetElement.java b/plugins/network-elements/midonet/src/com/cloud/network/element/MidoNetElement.java
deleted file mode 100644
index c85cb38b97e..00000000000
--- a/plugins/network-elements/midonet/src/com/cloud/network/element/MidoNetElement.java
+++ /dev/null
@@ -1,1635 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.cloud.network.element;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-
-import javax.inject.Inject;
-import javax.naming.ConfigurationException;
-import javax.ws.rs.core.MultivaluedMap;
-
-import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
-import org.apache.log4j.Logger;
-import org.midonet.client.MidonetApi;
-import org.midonet.client.dto.DtoRule;
-import org.midonet.client.dto.DtoRule.DtoRange;
-import org.midonet.client.exception.HttpInternalServerError;
-import org.midonet.client.resource.Bridge;
-import org.midonet.client.resource.BridgePort;
-import org.midonet.client.resource.DhcpHost;
-import org.midonet.client.resource.DhcpSubnet;
-import org.midonet.client.resource.Port;
-import org.midonet.client.resource.ResourceCollection;
-import org.midonet.client.resource.Route;
-import org.midonet.client.resource.Router;
-import org.midonet.client.resource.RouterPort;
-import org.midonet.client.resource.Rule;
-import org.midonet.client.resource.RuleChain;
-import org.springframework.stereotype.Component;
-
-import com.cloud.agent.api.to.FirewallRuleTO;
-import com.cloud.agent.api.to.PortForwardingRuleTO;
-import com.cloud.configuration.Config;
-import com.cloud.deploy.DeployDestination;
-import com.cloud.exception.ConcurrentOperationException;
-import com.cloud.exception.InsufficientCapacityException;
-import com.cloud.exception.ResourceUnavailableException;
-import com.cloud.network.IpAddress;
-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.NetworkModel;
-import com.cloud.network.Networks;
-import com.cloud.network.PhysicalNetworkServiceProvider;
-import com.cloud.network.PublicIpAddress;
-import com.cloud.network.rules.FirewallRule;
-import com.cloud.network.rules.PortForwardingRule;
-import com.cloud.network.rules.StaticNat;
-import com.cloud.network.vpc.VpcManager;
-import com.cloud.offering.NetworkOffering;
-import com.cloud.user.AccountManager;
-import com.cloud.user.AccountVO;
-import com.cloud.user.dao.AccountDao;
-import com.cloud.utils.Pair;
-import com.cloud.utils.component.AdapterBase;
-import com.cloud.utils.component.PluggableService;
-import com.cloud.utils.net.NetUtils;
-import com.cloud.vm.NicProfile;
-import com.cloud.vm.NicVO;
-import com.cloud.vm.ReservationContext;
-import com.cloud.vm.VirtualMachine;
-import com.cloud.vm.VirtualMachineProfile;
-import com.cloud.vm.dao.NicDao;
-import com.sun.jersey.core.util.MultivaluedMapImpl;
-
-@Component
-public class MidoNetElement extends AdapterBase implements ConnectivityProvider, DhcpServiceProvider, SourceNatServiceProvider, StaticNatServiceProvider, IpDeployer,
- PortForwardingServiceProvider, FirewallServiceProvider, PluggableService {
-
- private static final Logger s_logger = Logger.getLogger(MidoNetElement.class);
-
- private static final Map<Service, Map<Capability, String>> capabilities = setCapabilities();
-
- protected UUID _providerRouterId = null;
-
- protected MidonetApi api;
-
- private static final Provider MidoNet = new Provider("MidoNet", false);
-
- public enum RuleChainCode {
- TR_PRE, TR_PRENAT, TR_PREFILTER, TR_POST, ACL_INGRESS, ACL_EGRESS
- }
-
- @Inject
- ConfigurationDao _configDao;
- @Inject
- protected NicDao _nicDao;
- @Inject
- NetworkModel _networkModel;
- @Inject
- VpcManager _vpcMgr;
- @Inject
- AccountManager _accountMgr;
- @Inject
- AccountDao _accountDao;
-
- public void setMidonetApi(MidonetApi api) {
- this.api = api;
- }
-
- public void setAccountDao(AccountDao aDao) {
- this._accountDao = aDao;
- }
-
- @Override
- public Map<Service, Map<Capability, String>> getCapabilities() {
- return capabilities;
- }
-
- @Override
- public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
- super.configure(name, params);
-
- String routerIdValue = _configDao.getValue(Config.MidoNetProviderRouterId.key());
- if (routerIdValue != null)
- _providerRouterId = UUID.fromString(routerIdValue);
-
- String value = _configDao.getValue(Config.MidoNetAPIServerAddress.key());
-
- if (value == null) {
- throw new ConfigurationException("Could not find midonet API location in config");
- }
-
- if (this.api == null) {
- s_logger.info("midonet API server address is " + value);
- setMidonetApi(new MidonetApi(value));
- this.api.enableLogging();
- }
-
- return true;
- }
-
- public boolean midoInNetwork(Network network) {
- if ((network.getTrafficType() == Networks.TrafficType.Public) && (network.getBroadcastDomainType() == Networks.BroadcastDomainType.Mido)) {
- return true;
- }
- if ((network.getTrafficType() == Networks.TrafficType.Guest) && (network.getBroadcastDomainType() == Networks.BroadcastDomainType.Mido)) {
- return true;
- }
- return false;
- }
-
- protected boolean canHandle(Network network, Service service) {
- Long physicalNetworkId = _networkModel.getPhysicalNetworkId(network);
- if (physicalNetworkId == null) {
- return false;
- }
-
- if (!_networkModel.isProviderEnabledInPhysicalNetwork(physicalNetworkId, getProvider().getName())) {
- return false;
- }
-
- if (service == null) {
- if (!_networkModel.isProviderForNetwork(getProvider(), network.getId())) {
- s_logger.trace("Element " + getProvider().getName() + " is not a provider for the network " + network);
- return false;
- }
- } else {
- if (!_networkModel.isProviderSupportServiceInNetwork(network.getId(), service, getProvider())) {
- s_logger.trace("Element " + getProvider().getName() + " doesn't support service " + service.getName() + " in the network " + network);
- return false;
- }
- }
-
- return true;
- }
-
- public void applySourceNat(Router tenantRouter, Router providerRouter, RouterPort tenantUplink, RouterPort providerDownlink, RuleChain pre, RuleChain post,
- PublicIpAddress addr) {
-
- boolean needAdd = true;
- String SNtag = "/SourceNat";
- String SNkey = "CS_nat";
-
- String snatIp = addr.getAddress().addr();
-
- String CsDesc = snatIp + SNtag;
-
- //determine, by use of the properties, if we already
- //added this rule. If we did, then we can skip it
- //by setting needAdd = false
- for (Rule rule : pre.getRules()) {
- Map<String, String> props = rule.getProperties();
- if (props == null) {
- continue;
- }
- String snatTag = props.get(SNkey);
- if (snatTag == null) {
- continue;
- }
-
- if (!snatTag.equals(CsDesc)) {
- continue;
- } else {
- needAdd = false;
- break;
- }
- }
-
- if (needAdd == false) {
- //we found that this rule exists already,
- // so lets skip adding it
- return;
- }
-
- Map<String, String> ruleProps = new HashMap<String, String>();
- ruleProps.put(SNkey, CsDesc);
-
- DtoRule.DtoNatTarget[] targets = new DtoRule.DtoNatTarget[] {new DtoRule.DtoNatTarget(snatIp, snatIp, 1, 65535)};
-
- // Set inbound (reverse SNAT) rule
- pre.addRule()
- .type(DtoRule.RevSNAT)
- .flowAction(DtoRule.Accept)
- .nwDstAddress(snatIp)
- .nwDstLength(32)
- .inPorts(new UUID[] {tenantUplink.getId()})
- .position(1)
- .properties(ruleProps)
- .create();
-
- // Set outbound (SNAT) rule
- post.addRule()
- .type(DtoRule.SNAT)
- .flowAction(DtoRule.Accept)
- .outPorts(new UUID[] {tenantUplink.getId()})
- .natTargets(targets)
- .position(1)
- .properties(ruleProps)
- .create();
-
- // Set up default route from tenant router to provider router
- tenantRouter.addRoute()
- .type("Normal")
- .weight(100)
- .srcNetworkAddr("0.0.0.0")
- .srcNetworkLength(0)
- .dstNetworkAddr("0.0.0.0")
- .dstNetworkLength(0)
- .nextHopPort(tenantUplink.getId())
- .create();
-
- // Set routes for traffic to the SNAT IP to come back from provider router
- providerRouter.addRoute()
- .type("Normal")
- .weight(100)
- .srcNetworkAddr("0.0.0.0")
- .srcNetworkLength(0)
- .dstNetworkAddr(snatIp)
- .dstNetworkLength(32)
- .nextHopPort(providerDownlink.getId())
- .create();
-
- // Default rule to accept traffic that has been DNATed
- post.addRule().type(DtoRule.RevDNAT).flowAction(DtoRule.Accept).create();
- }
-
- public String getAccountUuid(Network network) {
- AccountVO acc = _accountDao.findById(network.getAccountId());
- return acc.getUuid();
- }
-
- public boolean associatePublicIP(Network network, final List<? extends PublicIpAddress> ipAddress) throws ResourceUnavailableException {
-
- s_logger.debug("associatePublicIP called with network: " + network.toString());
- /*
- * Get Mido Router for this network and set source rules
- * These should only be allocated inside the for loop, because
- * this function could be called as a part of network cleanup. In
- * that case, we do not want to recreate the guest network or
- * any ports.
- */
- boolean resources = false;
- Router tenantRouter = null;
- Router providerRouter = null;
- RouterPort[] ports = null;
-
- RouterPort tenantUplink = null;
- RouterPort providerDownlink = null;
-
- RuleChain preNat = null;
- RuleChain post = null;
- String accountIdStr = null;
- String routerName = null;
-
- // Set Source NAT rules on router
- for (PublicIpAddress ip : ipAddress) {
- // ip is the external one we sourcenat to
- if (ip.isSourceNat()) {
- if (resources == false) {
- tenantRouter = getOrCreateGuestNetworkRouter(network);
- providerRouter = api.getRouter(_providerRouterId);
- ports = getOrCreateProviderRouterPorts(tenantRouter, providerRouter);
-
- tenantUplink = ports[0];
- providerDownlink = ports[1];
-
- accountIdStr = getAccountUuid(network);
- boolean isVpc = getIsVpc(network);
- long id = getRouterId(network, isVpc);
- routerName = getRouterName(isVpc, id);
-
- preNat = getChain(accountIdStr, routerName, RuleChainCode.TR_PRENAT);
- post = api.getChain(tenantRouter.getOutboundFilterId());
- resources = true;
- }
-
- applySourceNat(tenantRouter, providerRouter, // Routers
- tenantUplink, providerDownlink, // Ports
- preNat, post, // Chains
- ip); // The IP
- }
- }
-
- return true;
- }
-
- /**
- * From interface IpDeployer
- *
- * @param network
- * @param ipAddress
- * @param services
- * @return
- * @throws ResourceUnavailableException
- */
- @Override
- public boolean applyIps(Network network, List<? extends PublicIpAddress> ipAddress, Set<Service> services) throws ResourceUnavailableException {
-
- s_logger.debug("applyIps called with network: " + network.toString());
- if (!this.midoInNetwork(network)) {
- return false;
- }
-
- boolean canHandle = true;
- for (Service service : services) {
- if (!canHandle(network, service)) {
- canHandle = false;
- break;
- }
- }
- if (canHandle) {
- return associatePublicIP(network, ipAddress);
- } else {
- return false;
- }
- }
-
- /**
- * From interface SourceNatServiceProvider
- */
- @Override
- public IpDeployer getIpDeployer(Network network) {
- s_logger.debug("getIpDeployer called with network " + network.toString());
- return this;
- }
-
- /**
- * From interface DHCPServiceProvider
- */
- @Override
- public boolean addDhcpEntry(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context)
- throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
-
- s_logger.debug("addDhcpEntry called with network: " + network.toString() + " nic: " + nic.toString() + " vm: " + vm.toString());
- if (!this.midoInNetwork(network)) {
- return false;
- }
- if (vm.getType() != VirtualMachine.Type.User) {
- return false;
- }
-
- // Get MidoNet bridge
- Bridge netBridge = getOrCreateNetworkBridge(network);
-
- // On bridge, get DHCP subnet (ensure it exists)
- ResourceCollection res = netBridge.getDhcpSubnets();
-
- DhcpSubnet sub = null;
-
- if (!res.isEmpty()) {
- sub = (DhcpSubnet)res.get(0);
- } else {
- Pair<String, Integer> cidrInfo = NetUtils.getCidr(network.getCidr());
- sub = netBridge.addDhcpSubnet();
-
- sub.subnetLength(cidrInfo.second());
- sub.subnetPrefix(cidrInfo.first());
- sub.defaultGateway(network.getGateway());
- List<String> dcs = new ArrayList<String>();
- dcs.add(dest.getDataCenter().getDns1());
- sub.dnsServerAddrs(dcs);
-
- sub.create();
- }
-
- // On DHCP subnet, add host using host details
- if (sub == null) {
- s_logger.error("Failed to create DHCP subnet on Midonet bridge");
- return false;
- } else {
- // Check if the host already exists - we may just be restarting an existing VM
- boolean isNewDhcpHost = true;
-
- for (DhcpHost dhcpHost : sub.getDhcpHosts()) {
- if (dhcpHost.getIpAddr().equals(nic.getIPv4Address())) {
- isNewDhcpHost = false;
- break;
- }
- }
-
- if (isNewDhcpHost) {
- DhcpHost host = sub.addDhcpHost();
- host.ipAddr(nic.getIPv4Address());
- host.macAddr(nic.getMacAddress());
- // This only sets the cloudstack internal name
- host.name(vm.getHostName());
-
- host.create();
- }
- }
-
- return true;
- }
-
- @Override
- public boolean configDhcpSupportForSubnet(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context)
- throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
- return false; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- @Override
- public boolean removeDhcpSupportForSubnet(Network network) {
- return false; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- private void removeMidonetStaticNAT(RuleChain preFilter, RuleChain preNat, RuleChain postNat, String floatingIp, String fixedIp, Router providerRouter) {
-
- // Delete filter (firewall) rules for this IP
- for (Rule rule : preFilter.getRules()) {
- String destAddr = rule.getNwDstAddress();
- if (destAddr != null && destAddr.equals(floatingIp)) {
- rule.delete();
- }
- }
-
- // Delete DNAT rules for this IP
- for (Rule rule : preNat.getRules()) {
- String destAddr = rule.getNwDstAddress();
- if (destAddr != null && destAddr.equals(floatingIp)) {
- rule.delete();
- }
- }
- // Delete SNAT rules for this IP
- for (Rule rule : postNat.getRules()) {
- String srcAddr = rule.getNwSrcAddress();
- if (srcAddr != null && srcAddr.equals(fixedIp)) {
- rule.delete();
- }
- }
-
- //we also created a route to go with this rule. That needs to be
- //deleted as well.
- for (Route route : providerRouter.getRoutes(new MultivaluedMapImpl())) {
- String routeDstAddr = route.getDstNetworkAddr();
- if (routeDstAddr != null && routeDstAddr.equals(floatingIp)) {
- route.delete();
- }
- }
- }
-
- private void addMidonetStaticNAT(RuleChain preFilter, RuleChain preNat, RuleChain postNat, String floatingIp, String fixedIp, RouterPort tenantUplink,
- RouterPort providerDownlink, Router providerRouter, Network network) {
-
- DtoRule.DtoNatTarget[] preTargets = new DtoRule.DtoNatTarget[] {new DtoRule.DtoNatTarget(fixedIp, fixedIp, 0, 0)};
-
- // Set inbound filter rule (allow return traffic to this IP)
- // Implemented as "jump to NAT chain" instead of ACCEPT;
- // this is to enforce that filter / firewall rules are evaluated
- // before NAT rules.
- preFilter.addRule().type(DtoRule.Jump).jumpChainId(preNat.getId()).nwDstAddress(floatingIp).nwDstLength(32).matchReturnFlow(true).position(1).create();
-
- // Allow ICMP replies (ICMP type 0, code 0 is ICMP reply)
- preFilter.addRule()
- .type(DtoRule.Jump)
- .jumpChainId(preNat.getId())
- .nwDstAddress(floatingIp)
- .nwDstLength(32)
- .nwProto(SimpleFirewallRule.stringToProtocolNumber("icmp"))
- .tpSrc(new DtoRange<Integer>(0, 0))
- .tpDst(new DtoRange<Integer>(0, 0))
- .position(2)
- .create();
-
- // We only want to set the default DROP rule for static NAT if
- // Firewall is handled by the Midonet plugin.
- // Set inbound filter rule (drop all traffic to this IP)
- if (canHandle(network, Service.Firewall)) {
- preFilter.addRule().type(DtoRule.Drop).nwDstAddress(floatingIp).nwDstLength(32).position(3).create();
- }
-
- // Set inbound (DNAT) rule
- preNat.addRule()
- .type(DtoRule.DNAT)
- .flowAction(DtoRule.Accept)
- .nwDstAddress(floatingIp)
- .nwDstLength(32)
- .inPorts(new UUID[] {tenantUplink.getId()})
- .natTargets(preTargets)
- .position(1)
- .create();
-
- DtoRule.DtoNatTarget[] postTargets = new DtoRule.DtoNatTarget[] {new DtoRule.DtoNatTarget(floatingIp, floatingIp, 0, 0)};
-
- // Set outbound (SNAT) rule
- // Match forward flow so that return traffic will be recognized
- postNat.addRule()
- .type(DtoRule.SNAT)
- .flowAction(DtoRule.Accept)
- .matchForwardFlow(true)
- .nwSrcAddress(fixedIp)
- .nwSrcLength(32)
- .outPorts(new UUID[] {tenantUplink.getId()})
- .natTargets(postTargets)
- .position(1)
- .create();
-
- // Set outbound (SNAT) rule
- // Match return flow to also allow out traffic which was marked as forward flow on way in
- postNat.addRule()
- .type(DtoRule.SNAT)
- .flowAction(DtoRule.Accept)
- .matchReturnFlow(true)
- .nwSrcAddress(fixedIp)
- .nwSrcLength(32)
- .outPorts(new UUID[] {tenantUplink.getId()})
- .natTargets(postTargets)
- .position(2)
- .create();
-
- // Set routes for traffic to the SNAT IP to come back from provider router
- providerRouter.addRoute()
- .type("Normal")
- .weight(100)
- .srcNetworkAddr("0.0.0.0")
- .srcNetworkLength(0)
- .dstNetworkAddr(floatingIp)
- .dstNetworkLength(32)
- .nextHopPort(providerDownlink.getId())
- .create();
- }
-
- /**
- * From interface StaticNatServiceProvider
- */
- @Override
- public boolean applyStaticNats(Network network, List<? extends StaticNat> rules) throws ResourceUnavailableException {
- s_logger.debug("applyStaticNats called with network: " + network.toString());
- if (!midoInNetwork(network)) {
- return false;
- }
- if (!canHandle(network, Service.StaticNat)) {
- return false;
- }
-
- boolean resources = false;
- Router tenantRouter = null;
- Router providerRouter = null;
-
- RouterPort[] ports = null;
-
- RouterPort tenantUplink = null;
- RouterPort providerDownlink = null;
-
- RuleChain preFilter = null;
- RuleChain preNat = null;
- RuleChain post = null;
-
- String accountIdStr = getAccountUuid(network);
- String networkUUIDStr = String.valueOf(network.getId());
-
- for (StaticNat rule : rules) {
- IpAddress sourceIp = _networkModel.getIp(rule.getSourceIpAddressId());
- String sourceIpAddr = sourceIp.getAddress().addr();
-
- if (resources == false) {
- tenantRouter = getOrCreateGuestNetworkRouter(network);
- providerRouter = api.getRouter(_providerRouterId);
-
- ports = getOrCreateProviderRouterPorts(tenantRouter, providerRouter);
-
- tenantUplink = ports[0];
- providerDownlink = ports[1];
-
- boolean isVpc = getIsVpc(network);
- long id = getRouterId(network, isVpc);
- String routerName = getRouterName(isVpc, id);
-
- preFilter = getChain(accountIdStr, routerName, RuleChainCode.TR_PREFILTER);
- preNat = getChain(accountIdStr, routerName, RuleChainCode.TR_PRENAT);
- post = api.getChain(tenantRouter.getOutboundFilterId());
- resources = true;
- }
-
- if (rule.isForRevoke()) {
- removeMidonetStaticNAT(preFilter, preNat, post, sourceIpAddr, rule.getDestIpAddress(), providerRouter);
- } else {
- addMidonetStaticNAT(preFilter, preNat, post, sourceIpAddr, rule.getDestIpAddress(), tenantUplink, providerDownlink, providerRouter, network);
- }
- }
-
- return true;
- }
-
- @Override
- public boolean applyFWRules(Network config, List<? extends FirewallRule> rulesToApply) throws ResourceUnavailableException {
- if (!midoInNetwork(config)) {
- return false;
- }
- if (canHandle(config, Service.Firewall)) {
- String accountIdStr = getAccountUuid(config);
- String networkUUIDStr = String.valueOf(config.getId());
- RuleChain preFilter = getChain(accountIdStr, networkUUIDStr, RuleChainCode.TR_PREFILTER);
- RuleChain preNat = getChain(accountIdStr, networkUUIDStr, RuleChainCode.TR_PRENAT);
-
- // Create a map of Rule description -> Rule for quicker lookups
- Map<String, Rule> existingRules = new HashMap<String, Rule>();
-
- for (Rule existingRule : preFilter.getRules()) {
- // The "whitelist" rules we're interested in are the Jump rules where src address is specified
- if (existingRule.getType().equals(DtoRule.Jump) && existingRule.getNwSrcAddress() != null) {
- String ruleString = new SimpleFirewallRule(existingRule).toStringArray()[0];
- existingRules.put(ruleString, existingRule);
- }
- }
-
- for (FirewallRule rule : rulesToApply) {
- if (rule.getState() == FirewallRule.State.Revoke || rule.getState() == FirewallRule.State.Add) {
- IpAddress dstIp = _networkModel.getIp(rule.getSourceIpAddressId());
- FirewallRuleTO ruleTO = new FirewallRuleTO(rule, null, dstIp.getAddress().addr());
-
- // Convert to string representation
- SimpleFirewallRule fwRule = new SimpleFirewallRule(ruleTO);
- String[] ruleStrings = fwRule.toStringArray();
-
- if (rule.getState() == FirewallRule.State.Revoke) {
- // Lookup in existingRules, delete if present
- for (String revokeRuleString : ruleStrings) {
- Rule foundRule = existingRules.get(revokeRuleString);
- if (foundRule != null) {
- foundRule.delete();
- }
- }
- } else if (rule.getState() == FirewallRule.State.Add) {
- // Lookup in existingRules, add if not present
- for (int i = 0; i < ruleStrings.length; i++) {
- String ruleString = ruleStrings[i];
- Rule foundRule = existingRules.get(ruleString);
- if (foundRule == null) {
- // Get the cidr for the related entry in the Source Cidrs list
- String relatedCidr = fwRule.sourceCidrs.get(i);
- Pair<String, Integer> cidrParts = NetUtils.getCidr(relatedCidr);
-
- // Create rule with correct proto, cidr, ACCEPT, dst IP
- Rule toApply =
- preFilter.addRule()
- .type(DtoRule.Jump)
- .jumpChainId(preNat.getId())
- .position(1)
- .nwSrcAddress(cidrParts.first())
- .nwSrcLength(cidrParts.second())
- .nwDstAddress(ruleTO.getSrcIp())
- .nwDstLength(32)
- .nwProto(SimpleFirewallRule.stringToProtocolNumber(rule.getProtocol()));
-
- if (rule.getProtocol().equals("icmp")) {
- // ICMP rules - reuse port fields
- // (-1, -1) means "allow all ICMP", so we don't set tpSrc / tpDst
- if (fwRule.icmpType != -1 | fwRule.icmpCode != -1) {
- toApply.tpSrc(new DtoRange(fwRule.icmpType, fwRule.icmpType)).tpDst(new DtoRange(fwRule.icmpCode, fwRule.icmpCode));
- }
- } else {
- toApply.tpDst(new DtoRange(fwRule.dstPortStart, fwRule.dstPortEnd));
- }
-
- toApply.create();
- }
- }
- }
- }
- }
- return true;
- } else {
- return true;
- }
- }
-
- @Override
- public Provider getProvider() {
- return MidoNet;
- }
-
- @Override
- public boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException,
- ResourceUnavailableException, InsufficientCapacityException {
- s_logger.debug("implement called with network: " + network.toString());
- if (!midoInNetwork(network)) {
- return false;
- }
-
- if (network.getTrafficType() == Networks.TrafficType.Guest) {
- // Create the Midonet bridge for this network
- Bridge netBridge = getOrCreateNetworkBridge(network);
- Router tenantRouter = getOrCreateGuestNetworkRouter(network);
-
- // connect router and bridge
- ensureBridgeConnectedToRouter(network, netBridge, tenantRouter);
- }
-
- return true;
- }
-
- @Override
- public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context)
- throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
- s_logger.debug("prepare called with network: " + network.toString() + " nic: " + nic.toString() + " vm: " + vm.toString());
- if (!midoInNetwork(network)) {
- return false;
- }
-
- if (nic.getTrafficType() == Networks.TrafficType.Guest && !canHandle(network, Service.StaticNat)) {
- return false;
- }
-
- if (nic.getTrafficType() == Networks.TrafficType.Guest || nic.getTrafficType() == Networks.TrafficType.Public &&
- nic.getBroadcastType() == Networks.BroadcastDomainType.Mido) {
- Bridge netBridge = getOrCreateNetworkBridge(network);
- if (nic.getTrafficType() == Networks.TrafficType.Public && vm.getVirtualMachine().getType() != VirtualMachine.Type.DomainRouter) {
- // Get provider router
- Router providerRouter = api.getRouter(_providerRouterId);
-
- Port[] ports = getOrCreatePublicBridgePorts(nic, netBridge, providerRouter);
-
- RouterPort providerDownlink = (RouterPort)ports[1];
-
- // Set route from router to bridge for this particular IP. Prepare
- // is called in both starting a new VM and restarting a VM, so the
- // NIC may
- boolean routeExists = false;
- for (Route route : providerRouter.getRoutes(new MultivaluedMapImpl())) {
- String ip4 = route.getDstNetworkAddr();
- if (ip4 != null && ip4.equals(nic.getIPv4Address())) {
- routeExists = true;
- break;
- }
- }
-
- if (!routeExists) {
- providerRouter.addRoute()
- .type("Normal")
- .weight(100)
- .srcNetworkAddr("0.0.0.0")
- .srcNetworkLength(0)
- .dstNetworkAddr(nic.getIPv4Address())
- .dstNetworkLength(32)
- .nextHopPort(providerDownlink.getId())
- .nextHopGateway(null)
- .create();
- }
- }
-
- // Add port on bridge
- BridgePort newPort = netBridge.addExteriorPort().create(); // returns wrapper resource of port
-
- // Set MidoNet port VIF ID to UUID of nic
- UUID nicUUID = getNicUUID(nic);
- newPort.vifId(nicUUID).update();
- }
-
- return true;
- }
-
- @Override
- public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException,
- ResourceUnavailableException {
- s_logger.debug("release called with network: " + network.toString() + " nic: " + nic.toString() + " vm: " + vm.toString());
- if (!midoInNetwork(network)) {
- return false;
- }
-
- UUID nicUUID = getNicUUID(nic);
- if (nic.getTrafficType() == Networks.TrafficType.Guest ||
- (nic.getTrafficType() == Networks.TrafficType.Public && nic.getBroadcastType() == Networks.BroadcastDomainType.Mido)) {
- // Seems like a good place to remove the port in midonet
- Bridge netBridge = getOrCreateNetworkBridge(network);
-
- Router providerRouter = api.getRouter(_providerRouterId);
-
- //remove the routes associated with this IP address
- for (Route route : providerRouter.getRoutes(new MultivaluedMapImpl())) {
- String routeDstAddr = route.getDstNetworkAddr();
- if (routeDstAddr != null && routeDstAddr.equals(nic.getIPv4Address())) {
- route.delete();
- }
- }
-
- for (BridgePort p : netBridge.getPorts()) {
- UUID vifID = p.getVifId();
- if (vifID != null && vifID.equals(nicUUID)) {
- // This is the MidoNet port which corresponds to the NIC we are releasing
-
- // Set VIF ID to null
- p.vifId(null).update();
-
- // Delete port
- p.delete();
- }
- }
- }
-
- return true;
- }
-
- @Override
- public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
- s_logger.debug("shutdown called with network: " + network.toString());
- if (!midoInNetwork(network)) {
- return false;
- }
-
- // Find Mido API server, remove ports from this network's bridge, remove bridge itself
- deleteNetworkBridges(network);
- if (network.getVpcId() == null) {
- deleteGuestNetworkRouters(network);
- }
-
- return true;
- }
-
- @Override
- public boolean destroy(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
- s_logger.debug("destroy called with network: " + network.toString());
- if (!midoInNetwork(network)) {
- return false;
- }
-
- deleteNetworkBridges(network);
- // if This is part of a VPC, then we do not want to delete the router.
- // we only delete the router when the VPC is destroyed
- if (network.getVpcId() == null) {
- deleteGuestNetworkRouters(network);
- }
-
- return true;
- }
-
- @Override
- public boolean isReady(PhysicalNetworkServiceProvider provider) {
- // We are always ready.
- return true;
- }
-
- @Override
- public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context) throws ConcurrentOperationException,
- ResourceUnavailableException {
- // Nothing to do here because the cleanup of the networks themselves clean up the resources.
- return true;
- }
-
- @Override
- public boolean canEnableIndividualServices() {
- // We can enable individual services, though this is still subject to
- // "VerifyServicesCombination
- return true;
- }
-
- @Override
- public boolean verifyServicesCombination(Set<Service> services) {
- if (services.contains(Service.Vpn) || services.contains(Service.Dns) || services.contains(Service.Lb) || services.contains(Service.UserData) ||
- services.contains(Service.SecurityGroup) || services.contains(Service.NetworkACL)) {
- // We don't implement any of these services, and we don't
- // want anyone else to do it for us. So if these services
- // exist, we can't handle it.
- return false;
- }
- return true;
- }
-
- @Override
- public boolean applyPFRules(Network network, List<PortForwardingRule> rules) throws ResourceUnavailableException {
- s_logger.debug("applyPFRules called with network " + network.toString());
- if (!midoInNetwork(network)) {
- return false;
- }
- if (!canHandle(network, Service.PortForwarding)) {
- return false;
- }
-
- String accountIdStr = getAccountUuid(network);
- String networkUUIDStr = String.valueOf(network.getId());
- RuleChain preNat = getChain(accountIdStr, networkUUIDStr, RuleChainCode.TR_PRENAT);
- RuleChain postNat = getChain(accountIdStr, networkUUIDStr, RuleChainCode.TR_POST);
- RuleChain preFilter = getChain(accountIdStr, networkUUIDStr, RuleChainCode.TR_PREFILTER);
- Router providerRouter = api.getRouter(_providerRouterId);
- Router tenantRouter = getOrCreateGuestNetworkRouter(network);
- RouterPort[] ports = getOrCreateProviderRouterPorts(tenantRouter, providerRouter);
- RouterPort providerDownlink = ports[1];
-
- // Rules in the preNat table
- Map<String, Rule> existingPreNatRules = new HashMap<String, Rule>();
- for (Rule existingRule : preNat.getRules()) {
- // The "port forwarding" rules we're interested in are dnat rules where src / dst ports are specified
- if (existingRule.getType().equals(DtoRule.DNAT) && existingRule.getTpDst() != null) {
- String ruleString = new SimpleFirewallRule(existingRule).toStringArray()[0];
- existingPreNatRules.put(ruleString, existingRule);
- }
- }
-
- /*
- * Counts of rules associated with an IP address. Use this to check
- * how many rules we have of a given IP address. When it reaches 0,
- * we can delete the route associated with it.
- */
- Map<String, Integer> ipRuleCounts = new HashMap<String, Integer>();
- for (Rule rule : preNat.getRules()) {
- String ip = rule.getNwDstAddress();
- if (ip != null && rule.getNwDstLength() == 32) {
- if (ipRuleCounts.containsKey(ip)) {
- ipRuleCounts.put(ip, new Integer(ipRuleCounts.get(ip).intValue() + 1));
- } else {
- ipRuleCounts.put(ip, new Integer(1));
- }
- }
- }
-
- /*
- * Routes associated with IP. When we delete all the rules associated
- * with a given IP, we can delete the route associated with it.
- */
- Map<String, Route> routes = new HashMap<String, Route>();
- for (Route route : providerRouter.getRoutes(new MultivaluedMapImpl())) {
- String ip = route.getDstNetworkAddr();
- if (ip != null && route.getDstNetworkLength() == 32) {
- routes.put(ip, route);
- }
- }
-
- for (PortForwardingRule rule : rules) {
- IpAddress dstIp = _networkModel.getIp(rule.getSourceIpAddressId());
- PortForwardingRuleTO ruleTO = new PortForwardingRuleTO(rule, null, dstIp.getAddress().addr());
- SimpleFirewallRule fwRule = new SimpleFirewallRule(ruleTO);
- String[] ruleStrings = fwRule.toStringArray();
-
- if (rule.getState() == FirewallRule.State.Revoke) {
- /*
- * Lookup in existingRules, delete if present
- * We need to delete from both the preNat table and the
- * postNat table.
- */
- for (String revokeRuleString : ruleStrings) {
- Rule foundPreNatRule = existingPreNatRules.get(revokeRuleString);
- if (foundPreNatRule != null) {
- String ip = foundPreNatRule.getNwDstAddress();
- // is this the last rule associated with this IP?
- Integer cnt = ipRuleCounts.get(ip);
- if (cnt != null) {
- if (cnt == 1) {
- ipRuleCounts.remove(ip);
- // no more rules for this IP. delete the route.
- Route route = routes.remove(ip);
- route.delete();
- } else {
- ipRuleCounts.put(ip, new Integer(ipRuleCounts.get(ip).intValue() - 1));
- }
- }
- foundPreNatRule.delete();
- }
- }
- } else if (rule.getState() == FirewallRule.State.Add) {
- for (int i = 0; i < ruleStrings.length; i++) {
- String ruleString = ruleStrings[i];
- Rule foundRule = existingPreNatRules.get(ruleString);
- if (foundRule == null) {
-
- String vmIp = ruleTO.getDstIp();
- String publicIp = dstIp.getAddress().addr();
- int privPortStart = ruleTO.getDstPortRange()[0];
- int privPortEnd = ruleTO.getDstPortRange()[1];
- int pubPortStart = ruleTO.getSrcPortRange()[0];
- int pubPortEnd = ruleTO.getSrcPortRange()[1];
-
- DtoRule.DtoNatTarget[] preTargets = new DtoRule.DtoNatTarget[] {new DtoRule.DtoNatTarget(vmIp, vmIp, privPortStart, privPortEnd)};
-
- Rule preNatRule =
- preNat.addRule()
- .type(DtoRule.DNAT)
- .flowAction(DtoRule.Accept)
- .nwDstAddress(publicIp)
- .nwDstLength(32)
- .tpDst(new DtoRange(pubPortStart, pubPortEnd))
- .natTargets(preTargets)
- .nwProto(SimpleFirewallRule.stringToProtocolNumber(rule.getProtocol()))
- .position(1);
-
- Integer cnt = ipRuleCounts.get(publicIp);
- if (cnt != null) {
- ipRuleCounts.put(publicIp, new Integer(cnt.intValue() + 1));
- } else {
- ipRuleCounts.put(publicIp, new Integer(1));
- }
- String preNatRuleStr = new SimpleFirewallRule(preNatRule).toStringArray()[0];
- existingPreNatRules.put(preNatRuleStr, preNatRule);
- preNatRule.create();
-
- if (routes.get(publicIp) == null) {
- Route route =
- providerRouter.addRoute()
- .type("Normal")
- .weight(100)
- .srcNetworkAddr("0.0.0.0")
- .srcNetworkLength(0)
- .dstNetworkAddr(publicIp)
- .dstNetworkLength(32)
- .nextHopPort(providerDownlink.getId());
- route.create();
- routes.put(publicIp, route);
- }
-
- // If Firewall is in our service offering, set up the
- // default firewall rule
- if (canHandle(network, Service.Firewall)) {
- boolean defaultBlock = false;
- for (Rule filterRule : preFilter.getRules()) {
- String pfDstIp = filterRule.getNwDstAddress();
- if (pfDstIp != null && filterRule.getNwDstAddress().equals(publicIp)) {
- defaultBlock = true;
- break;
- }
- }
- if (!defaultBlock) {
- preFilter.addRule().type(DtoRule.Drop).nwDstAddress(publicIp).nwDstLength(32).create();
- }
- }
- }
- }
- }
- }
- return true;
- }
-
- private static Map<Service, Map<Capability, String>> setCapabilities() {
- Map<Service, Map<Capability, String>> capabilities = new HashMap<Service, Map<Capability, String>>();
-
- // L2 Support : SDN provisioning
- capabilities.put(Service.Connectivity, null);
-
- // L3 Support : Generic?
- capabilities.put(Service.Gateway, null);
-
- // L3 Support : DHCP
- Map<Capability, String> dhcpCapabilities = new HashMap<Capability, String>();
- capabilities.put(Service.Dhcp, dhcpCapabilities);
-
- // L3 Support : SourceNat
- Map<Capability, String> sourceNatCapabilities = new HashMap<Capability, String>();
- //sourceNatCapabilities.putAll(capabilities.get(Service.SourceNat));
- sourceNatCapabilities.put(Capability.SupportedSourceNatTypes, "peraccount");
- //sourceNatCapabilities.putAll(capabilities.get(Service.SourceNat));
- sourceNatCapabilities.put(Capability.RedundantRouter, "false");
- capabilities.put(Service.SourceNat, sourceNatCapabilities);
-
- // L3 Support : Port Forwarding
- capabilities.put(Service.PortForwarding, null);
-
- // L3 support : StaticNat
- capabilities.put(Service.StaticNat, null);
-
- // Set capabilities for Firewall service
- Map<Capability, String> firewallCapabilities = new HashMap<Capability, String>();
- firewallCapabilities.put(Capability.TrafficStatistics, "per public ip");
- firewallCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp");
- firewallCapabilities.put(Capability.SupportedTrafficDirection, "ingress");
- firewallCapabilities.put(Capability.MultipleIps, "true");
- capabilities.put(Service.Firewall, firewallCapabilities);
-
- return capabilities;
- }
-
- private String getChainName(String routerName, RuleChainCode chainCode) {
- return getChainName("", routerName, chainCode);
- }
-
- private String getChainName(String networkId, String routerName, RuleChainCode chainCode) {
-
- String chain = "";
-
- switch (chainCode) {
- case TR_PRE:
- chain = "pre-routing";
- break;
- case TR_PREFILTER:
- chain = "pre-filter";
- break;
- case TR_PRENAT:
- chain = "pre-nat";
- break;
- case TR_POST:
- chain = "post-routing";
- break;
- case ACL_INGRESS:
- chain = "ACL-ingress-" + networkId;
- break;
- case ACL_EGRESS:
- chain = "ACL-egress-" + networkId;
- break;
- }
-
- return routerName + "-tenantrouter-" + chain;
- }
-
- protected RuleChain getChain(String accountUuid, String routerName, RuleChainCode chainCode) {
- return getChain("", accountUuid, routerName, chainCode);
- }
-
- protected RuleChain getChain(String networkId, String accountUuid, String routerName, RuleChainCode chainCode) {
- String chainName = getChainName(networkId, routerName, chainCode);
-
- MultivaluedMap findChain = new MultivaluedMapImpl();
- findChain.add("tenant_id", accountUuid);
-
- ResourceCollection<RuleChain> ruleChains = api.getChains(findChain);
-
- for (RuleChain chain : ruleChains) {
- if (chain.getName().equals(chainName)) {
- return chain;
- }
- }
-
- return null;
- }
-
- protected RouterPort[] getOrCreateProviderRouterPorts(Router tenantRouter, Router providerRouter) {
- RouterPort[] ports = new RouterPort[2];
-
- RouterPort tenantUplink = null;
- RouterPort providerDownlink = null;
-
- // Check if the ports and connection already exist
- for (Port peerPort : tenantRouter.getPeerPorts((new MultivaluedMapImpl()))) {
- if (peerPort != null && peerPort instanceof RouterPort) {
- RouterPort checkPort = (RouterPort)peerPort;
- if (checkPort.getDeviceId().compareTo(providerRouter.getId()) == 0) {
- providerDownlink = checkPort;
- tenantUplink = (RouterPort)api.getPort(checkPort.getPeerId());
- break;
- }
- }
- }
-
- // Create the ports and connection if they don't exist
- if (providerDownlink == null) {
- // Add interior port on router side, with network details
- providerDownlink = providerRouter.addInteriorRouterPort().networkAddress("169.254.255.0").networkLength(32).portAddress("169.254.255.1").create();
- tenantUplink = tenantRouter.addInteriorRouterPort().networkAddress("169.254.255.0").networkLength(32).portAddress("169.254.255.2").create();
-
- // Link them up
- providerDownlink.link(tenantUplink.getId()).update();
- }
-
- ports[0] = tenantUplink;
- ports[1] = providerDownlink;
-
- return ports;
- }
-
- private Port[] getOrCreatePublicBridgePorts(NicProfile nic, Bridge publicBridge, Router providerRouter) {
- Port[] ports = new Port[2];
-
- BridgePort bridgeUplink = null;
- RouterPort providerDownlink = null;
-
- // Check if the ports and connection already exist
- for (Port peerPort : publicBridge.getPeerPorts()) {
- if (peerPort != null && peerPort instanceof RouterPort) {
- RouterPort checkPort = (RouterPort)peerPort;
- // Check it's a port on the providerRouter with the right gateway address
- if (checkPort.getDeviceId().compareTo(providerRouter.getId()) == 0 && checkPort.getPortAddress().equals(nic.getIPv4Gateway())) {
- providerDownlink = checkPort;
- bridgeUplink = (BridgePort)api.getPort(checkPort.getPeerId());
- break;
- }
- }
- }
-
- // Create the ports and connection if they don't exist
- if (providerDownlink == null) {
- String cidr = NetUtils.ipAndNetMaskToCidr(nic.getIPv4Gateway(), nic.getIPv4Netmask());
- String cidrSubnet = NetUtils.getCidrSubNet(cidr);
- int cidrSize = (int)NetUtils.getCidrSize(NetUtils.cidr2Netmask(cidr));
- String gateway = nic.getIPv4Gateway();
-
- // Add interior port on router side, with network details
- providerDownlink = providerRouter.addInteriorRouterPort().networkAddress(cidrSubnet).networkLength(cidrSize).portAddress(gateway).create();
- bridgeUplink = publicBridge.addInteriorPort().create();
-
- // Link them up
- providerDownlink.link(bridgeUplink.getId()).update();
-
- }
-
- ports[0] = bridgeUplink;
- ports[1] = providerDownlink;
-
- return ports;
- }
-
- private void ensureBridgeConnectedToRouter(Network network, Bridge netBridge, Router netRouter) {
- if (getBridgeToRouterPort(network, netBridge, netRouter) == null) {
- connectBridgeToRouter(network, netBridge, netRouter);
- }
- }
-
- private BridgePort getBridgeToRouterPort(Network network, Bridge netBridge, Router netRouter) {
- for (Port p : netBridge.getPeerPorts()) {
- if (p.getClass().equals(BridgePort.class)) {
- BridgePort bp = (BridgePort)p;
- if (bp.getPeerId().compareTo(netRouter.getId()) == 0) {
- return bp;
- }
- }
- }
- return null;
- }
-
- /*
- * resetEgressACLFilter sets the Egress ACL Filter back to its initial
- * state - drop everything. This needs to be called when all Egress
- * ACL rules are deleted, so we can start allowing all Egress traffic
- * again
- */
- protected void resetEgressACLFilter(Network network) {
- boolean isVpc = getIsVpc(network);
- long id = getRouterId(network, isVpc);
- String routerName = getRouterName(isVpc, id);
-
- RuleChain egressChain = getChain(String.valueOf(network.getId()), getAccountUuid(network), routerName, RuleChainCode.ACL_EGRESS);
-
- // Clear all the rules out
- for (Rule rule : egressChain.getRules()) {
- rule.delete();
- }
-
- // Add a matchForwardFlow rule so that we can accept all return traffic
- egressChain.addRule().type(DtoRule.Accept).matchForwardFlow(true).position(1).create();
- }
-
- protected RuleChain getOrInitEgressACLFilter(Network network) {
- boolean isVpc = getIsVpc(network);
- long id = getRouterId(network, isVpc);
- String routerName = getRouterName(isVpc, id);
-
- RuleChain egressChain = getChain(String.valueOf(network.getId()), getAccountUuid(network), routerName, RuleChainCode.ACL_EGRESS);
-
- // Rules set by the user will have a protocol, so we count the ACL
- // rules by counting how much have the nwProto field set.
- int totalRules = 0;
- for (Rule rule : egressChain.getRules()) {
- if (rule.getNwProto() != 0) {
- totalRules++;
- }
- }
-
- if (totalRules > 0) {
- // There are already rules present, no need to init.
- return egressChain;
- } else {
- // We need to delete any placeholder rules
- for (Rule rule : egressChain.getRules()) {
- rule.delete();
- }
- }
-
- int pos = 1;
- // If it is ARP, accept it
- egressChain.addRule().type(DtoRule.Accept).dlType(0x0806).position(pos++).create();
-
- // If it is ICMP to the router, accept that
- egressChain.addRule()
- .type(DtoRule.Accept)
- .nwProto(SimpleFirewallRule.stringToProtocolNumber("icmp"))
- .nwDstAddress(network.getGateway())
- .nwDstLength(32)
- .position(pos++)
- .create();
-
- // Everything else gets dropped
- egressChain.addRule().type(DtoRule.Drop).position(pos).create();
-
- return egressChain;
- }
-
- private void connectBridgeToRouter(Network network, Bridge netBridge, Router netRouter) {
-
- boolean isVpc = getIsVpc(network);
- long id = getRouterId(network, isVpc);
- String routerName = getRouterName(isVpc, id);
- String accountIdStr = getAccountUuid(network);
-
- // Add interior port on bridge side
- BridgePort bridgePort = netBridge.addInteriorPort().create();
-
- // Add interior port on router side, with network details
- RouterPort routerPort = netRouter.addInteriorRouterPort();
- String cidr = network.getCidr();
- String cidrSubnet = NetUtils.getCidrSubNet(cidr);
- int cidrSize = (int)NetUtils.getCidrSize(NetUtils.cidr2Netmask(cidr));
-
- routerPort.networkAddress(cidrSubnet);
- routerPort.networkLength(cidrSize);
- routerPort.portAddress(network.getGateway());
-
- // If this is a VPC, then we will be using NetworkACLs, which is
- // implemented via chains on the router port to that network.
- if (getIsVpc(network)) {
- // Create ACL filter chain for traffic coming INTO the network
- // (outbound from the port
- int pos = 1;
-
- RuleChain inc = api.addChain().name(getChainName(String.valueOf(network.getId()), routerName, RuleChainCode.ACL_INGRESS)).tenantId(accountIdStr).create();
-
- // If it is ARP, accept it
- inc.addRule().type(DtoRule.Accept).dlType(0x0806).position(pos++).create();
-
- // If it is ICMP to the router, accept that
- inc.addRule()
- .type(DtoRule.Accept)
- .nwProto(SimpleFirewallRule.stringToProtocolNumber("icmp"))
- .nwDstAddress(network.getGateway())
- .nwDstLength(32)
- .position(pos++)
- .create();
-
- // If it is connection tracked, accept that as well
- inc.addRule().type(DtoRule.Accept).matchReturnFlow(true).position(pos++).create();
-
- inc.addRule().type(DtoRule.Drop).position(pos).create();
-
- //
- RuleChain out = api.addChain().name(getChainName(String.valueOf(network.getId()), routerName, RuleChainCode.ACL_EGRESS)).tenantId(accountIdStr).create();
-
- // Creating the first default rule here that does nothing
- // but start connection tracking.
- out.addRule().type(DtoRule.Accept).matchForwardFlow(true).position(1).create();
-
- routerPort.outboundFilterId(inc.getId());
- routerPort.inboundFilterId(out.getId());
- }
-
- routerPort.create();
-
- // Link them up
- bridgePort.link(routerPort.getId()).update();
-
- // Set up default route from router to subnet
- netRouter.addRoute()
- .type("Normal")
- .weight(100)
- .srcNetworkAddr("0.0.0.0")
- .srcNetworkLength(0)
- .dstNetworkAddr(cidrSubnet)
- .dstNetworkLength(cidrSize)
- .nextHopPort(routerPort.getId())
- .nextHopGateway(null)
- .create();
- }
-
- private Bridge getOrCreateNetworkBridge(Network network) {
- // Find the single bridge for this network, create if doesn't exist
- return getOrCreateNetworkBridge(network.getId(), getAccountUuid(network));
- }
-
- private Bridge getOrCreateNetworkBridge(long networkID, String accountUuid) {
- Bridge netBridge = getNetworkBridge(networkID, accountUuid);
- if (netBridge == null) {
-
- String networkUUIDStr = String.valueOf(networkID);
-
- s_logger.debug("Attempting to create guest network bridge");
- try {
- netBridge = api.addBridge().tenantId(accountUuid).name(networkUUIDStr).create();
- } catch (HttpInternalServerError ex) {
- s_logger.warn("Bridge creation failed, retrying bridge get in case it now exists.", ex);
- netBridge = getNetworkBridge(networkID, accountUuid);
- }
- }
- return netBridge;
- }
-
- private Bridge getNetworkBridge(long networkID, String accountUuid) {
-
- MultivaluedMap qNetBridge = new MultivaluedMapImpl();
- String networkUUIDStr = String.valueOf(networkID);
- qNetBridge.add("tenant_id", accountUuid);
-
- for (Bridge b : this.api.getBridges(qNetBridge)) {
- if (b.getName().equals(networkUUIDStr)) {
- return b;
- }
- }
-
- return null;
- }
-
- protected boolean getIsVpc(Network network) {
- return (network.getVpcId() != null);
- }
-
- protected long getRouterId(Network network, boolean isVpc) {
- if (isVpc) {
- return network.getVpcId();
- } else {
- return network.getId();
- }
- }
-
- private Router getOrCreateGuestNetworkRouter(Network network) {
- // Find the single bridge for this (isolated) guest network, create if doesn't exist
- boolean isVpc = getIsVpc(network);
- long id = getRouterId(network, isVpc);
-
- return getOrCreateGuestNetworkRouter(id, getAccountUuid(network), isVpc);
-
- }
-
- protected String getRouterName(boolean isVpc, long id) {
- if (isVpc) {
- return "VPC" + String.valueOf(id);
- } else {
- return String.valueOf(id);
- }
- }
-
- protected Router createRouter(long id, String accountUuid, boolean isVpc) {
-
- String routerName = getRouterName(isVpc, id);
-
- //Set up rule chains
- RuleChain pre = api.addChain().name(getChainName(routerName, RuleChainCode.TR_PRE)).tenantId(accountUuid).create();
- RuleChain post = api.addChain().name(getChainName(routerName, RuleChainCode.TR_POST)).tenantId(accountUuid).create();
-
- // Set up NAT and filter chains for pre-routing
- RuleChain preFilter = api.addChain().name(getChainName(routerName, RuleChainCode.TR_PREFILTER)).tenantId(accountUuid).create();
- RuleChain preNat = api.addChain().name(getChainName(routerName, RuleChainCode.TR_PRENAT)).tenantId(accountUuid).create();
-
- // Hook the chains in - first jump to Filter chain, then jump to Nat chain
- pre.addRule().type(DtoRule.Jump).jumpChainId(preFilter.getId()).position(1).create();
- pre.addRule().type(DtoRule.Jump).jumpChainId(preNat.getId()).position(2).create();
-
- return api.addRouter().tenantId(accountUuid).name(routerName).inboundFilterId(pre.getId()).outboundFilterId(post.getId()).create();
- }
-
- private Router getOrCreateGuestNetworkRouter(long id, String accountUuid, boolean isVpc) {
- Router tenantRouter = getGuestNetworkRouter(id, accountUuid, isVpc);
- if (tenantRouter == null) {
- tenantRouter = createRouter(id, accountUuid, isVpc);
- }
- return tenantRouter;
- }
-
- private Router getGuestNetworkRouter(long id, String accountUuid, boolean isVpc) {
-
- MultivaluedMap qNetRouter = new MultivaluedMapImpl();
- String routerName = getRouterName(isVpc, id);
-
- qNetRouter.add("tenant_id", accountUuid);
-
- for (Router router : api.getRouters(qNetRouter)) {
- if (router.getName().equals(routerName)) {
- return router;
- }
- }
-
- return null;
- }
-
- private UUID getNicUUID(NicProfile nic) {
- NicVO nicvo = _nicDao.findById(nic.getId());
- return UUID.fromString(nicvo.getUuid());
- }
-
- private void cleanBridge(Bridge br) {
-
- for (Port peerPort : br.getPeerPorts()) {
- if (peerPort != null && peerPort instanceof RouterPort) {
- RouterPort checkPort = (RouterPort)peerPort;
- if (checkPort.getType().equals("ExteriorRouter")) {
- checkPort.vifId(null).update();
- } else if (checkPort.getType().equals("InteriorRouter")) {
- checkPort.unlink();
- }
- checkPort.delete();
- }
- }
-
- for (BridgePort p : br.getPorts()) {
-
- if (p.getType().equals("ExteriorBridge")) {
- // Set VIF ID to null
- p.vifId(null).update();
- }
-
- if (p.getType().equals("InteriorBridge")) {
- p.unlink();
- }
-
- // Delete port
- p.delete();
- }
- }
-
- private void deleteNetworkBridges(Network network) {
- String accountUuid = getAccountUuid(network);
- long networkID = network.getId();
-
- Bridge netBridge = getNetworkBridge(networkID, accountUuid);
- if (netBridge != null) {
-
- cleanBridge(netBridge);
-
- // Delete DHCP subnets
- for (Object dhcpSubnet : netBridge.getDhcpSubnets()) {
- DhcpSubnet sub = (DhcpSubnet)dhcpSubnet;
- sub.delete();
- }
-
- netBridge.delete();
- }
- }
-
- private void deleteGuestNetworkRouters(Network network) {
- String accountUuid = getAccountUuid(network);
- boolean isVpc = getIsVpc(network);
- long id = getRouterId(network, isVpc);
-
- Router tenantRouter = getGuestNetworkRouter(id, accountUuid, isVpc);
-
- // Delete any peer ports corresponding to this router
- for (Port peerPort : tenantRouter.getPeerPorts((new MultivaluedMapImpl()))) {
- if (peerPort != null && peerPort instanceof RouterPort) {
- RouterPort checkPort = (RouterPort)peerPort;
- if (checkPort.getType().equals("ExteriorRouter")) {
- checkPort.vifId(null).update();
- } else if (checkPort.getType().equals("InteriorRouter")) {
- checkPort.unlink();
- }
- checkPort.delete();
- } else if (peerPort != null && peerPort instanceof BridgePort) {
- BridgePort checkPort = (BridgePort)peerPort;
- if (checkPort.getType().equals("ExteriorBridge")) {
- checkPort.vifId(null).update();
- } else if (checkPort.getType().equals("InteriorBridge")) {
- checkPort.unlink();
- }
- checkPort.delete();
- }
- }
-
- if (tenantRouter != null) {
- // Remove all peer ports if any exist
- for (RouterPort p : tenantRouter.getPorts(new MultivaluedMapImpl())) {
- if (p.getType().equals("ExteriorRouter")) {
- // Set VIF ID to null
- p.vifId(null).update();
- // the port might have some chains associated with it
- }
-
- if (p.getType().equals("InteriorRouter")) {
- p.unlink();
- }
-
- // Delete port
- p.delete();
- }
-
- // Remove inbound and outbound filter chains
- String accountIdStr = String.valueOf(accountUuid);
- String routerName = getRouterName(isVpc, id);
-
- RuleChain pre = api.getChain(tenantRouter.getInboundFilterId());
- RuleChain preFilter = getChain(accountIdStr, routerName, RuleChainCode.TR_PREFILTER);
- RuleChain preNat = getChain(accountIdStr, routerName, RuleChainCode.TR_PRENAT);
- RuleChain post = api.getChain(tenantRouter.getOutboundFilterId());
-
- pre.delete();
- preFilter.delete();
- preNat.delete();
- post.delete();
-
- // Remove routes
- for (Route r : tenantRouter.getRoutes(new MultivaluedMapImpl())) {
- r.delete();
- }
-
- tenantRouter.delete();
- }
- }
-
- @Override
- public List<Class<?>> getCommands() {
- // MidoNet does not implement any commands, so we return an empty list.
- return new ArrayList<Class<?>>();
- }
-}
diff --git a/plugins/network-elements/midonet/src/com/cloud/network/element/SimpleFirewallRule.java b/plugins/network-elements/midonet/src/com/cloud/network/element/SimpleFirewallRule.java
deleted file mode 100644
index 664132f54ed..00000000000
--- a/plugins/network-elements/midonet/src/com/cloud/network/element/SimpleFirewallRule.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package com.cloud.network.element;
-
-import java.util.ArrayList;
-import java.util.List;
-// Used for translation between MidoNet firewall rules and
-// CloudStack firewall rules
-
-import org.midonet.client.dto.DtoRule;
-import org.midonet.client.resource.Rule;
-
-import com.google.common.collect.BiMap;
-import com.google.common.collect.HashBiMap;
-
-import com.cloud.agent.api.to.FirewallRuleTO;
-import com.cloud.agent.api.to.NetworkACLTO;
-import com.cloud.agent.api.to.PortForwardingRuleTO;
-
-public class SimpleFirewallRule {
-
- public List<String> sourceCidrs;
- public String protocol;
- public String dstIp;
- public int dstPortStart = 0;
- public int dstPortEnd = 0;
- public int icmpType = 0;
- public int icmpCode = 0;
-
- private static BiMap<Integer, String> protocolNumberToString;
- static {
- protocolNumberToString = HashBiMap.create();
- protocolNumberToString.put(1, "icmp");
- protocolNumberToString.put(6, "tcp");
- protocolNumberToString.put(17, "udp");
- protocolNumberToString.put(0, "none");
- }
-
- public SimpleFirewallRule(FirewallRuleTO rule) {
- // Destination IP (confusingly called SourceIP in FirewallRule attributes)
- dstIp = rule.getSrcIp();
- protocol = rule.getProtocol();
-
- if ("icmp".equals(protocol)) {
- icmpType = rule.getIcmpType();
- icmpCode = rule.getIcmpCode();
- } else {
- int[] portNumbers = rule.getSrcPortRange();
-
- // if port start and end are not set, they
- // should be 0,0, and that's already the case
- if (portNumbers != null && portNumbers.length == 2) {
- dstPortStart = portNumbers[0];
- dstPortEnd = portNumbers[1];
- }
- }
-
- sourceCidrs = rule.getSourceCidrList();
-
- // If no CIDRs specified, it is an "all sources" rule
- if (sourceCidrs == null || sourceCidrs.isEmpty()) {
- sourceCidrs = new ArrayList<String>();
- sourceCidrs.add("0.0.0.0/0");
- }
- }
-
- public SimpleFirewallRule(NetworkACLTO rule) {
- dstIp = "null";
- protocol = rule.getProtocol();
-
- if ("icmp".equals(protocol)) {
- icmpType = rule.getIcmpType();
- icmpCode = rule.getIcmpCode();
- } else {
- int[] portNumbers = rule.getSrcPortRange();
-
- // if port start and end are not set, they
- // should be 0,0, and that's already the case
- if (portNumbers != null && portNumbers.length == 2) {
- dstPortStart = portNumbers[0];
- dstPortEnd = portNumbers[1];
- }
- }
-
- sourceCidrs = rule.getSourceCidrList();
-
- // If no CIDRs specified, it is an "all sources" rule
- if (sourceCidrs == null || sourceCidrs.isEmpty()) {
- sourceCidrs = new ArrayList<String>();
- sourceCidrs.add("0.0.0.0/0");
- }
- }
-
- public SimpleFirewallRule(PortForwardingRuleTO rule) {
- dstIp = rule.getSrcIp();
- protocol = rule.getProtocol();
-
- int[] srcPortNumbers = rule.getSrcPortRange();
- int[] dstPortNumbers = rule.getDstPortRange();
-
- // if port start and end are not set, they
- // should be 0,0, and that's already the case
- if (srcPortNumbers != null && srcPortNumbers.length == 2 && dstPortNumbers != null && dstPortNumbers.length == 2) {
- dstPortStart = dstPortNumbers[0];
- dstPortEnd = srcPortNumbers[0];
- }
-
- sourceCidrs = new ArrayList<String>();
- sourceCidrs.add(rule.getDstIp());
- }
-
- public SimpleFirewallRule(Rule rule) {
-
- String sourceIP = rule.getNwSrcAddress();
- int sourceLength = rule.getNwSrcLength();
-
- sourceCidrs = new ArrayList<String>();
- /*
- * Only one IP in the CIDR list
- * Port Forwarding Rules don't have sourceCidrs, but they do have
- * targets. Use those instead if they exist.
- */
- DtoRule.DtoNatTarget[] targets = rule.getNatTargets();
- if (targets != null) {
- sourceCidrs.add(targets[0].addressFrom);
- } else {
- sourceCidrs.add(String.format("%s/%d", sourceIP, sourceLength));
- }
-
- int protoNum = rule.getNwProto();
- protocol = SimpleFirewallRule.protocolNumberToString(protoNum);
-
- dstIp = rule.getNwDstAddress();
-
- if ("icmp".equals(protocol)) {
- if (rule.getTpSrc() != null && rule.getTpDst() != null) {
- icmpType = rule.getTpSrc().start;
- icmpCode = rule.getTpDst().start;
- } else {
- icmpType = -1;
- icmpCode = -1;
- }
-
- } else {
- /*
- * If this is port forwarding, we want to take the start
- * port for the public port range, and the start port for
- * the private port range to uniquely identify this rule.
- */
- if (targets != null) {
- dstPortStart = targets[0].portFrom;
- } else {
- dstPortStart = rule.getTpDst().start;
- }
- dstPortEnd = rule.getTpDst().end;
- }
-
- // cidr, protocol, dstIp, dstPortStart, dstPortEnd, icmpType, icmpCode);
- }
-
- public static String protocolNumberToString(int protocolNumber) {
- return protocolNumberToString.get(protocolNumber);
- }
-
- public static int stringToProtocolNumber(String protoString) {
- return protocolNumberToString.inverse().get(protoString);
- }
-
- public int getFieldOne() {
- if (protocol.equals("icmp")) {
- return icmpType;
-
- } else {
- return dstPortStart;
- }
- }
-
- public int getFieldTwo() {
- if (protocol.equals("icmp")) {
- return icmpCode;
- } else {
- return dstPortEnd;
- }
- }
-
- public String[] toStringArray() {
- List<String> stringRules = new ArrayList<String>();
-
- // Create a rule string per source CIDR, since each MidoNet
- // rule is for one CIDR
- for (String sourceCidr : sourceCidrs) {
-
- // Follows the rule String format defined in SetFirewallRulesCommand.java::generateFirewallRules()
- int field1 = getFieldOne();
- int field2 = getFieldTwo();
-
- String stringRule = String.format("%s:%s:%d:%d:%s:", dstIp, protocol, field1, field2, sourceCidr);
- stringRules.add(stringRule);
- }
- String[] stringArray = new String[stringRules.size()];
- return stringRules.toArray(stringArray);
- }
-}
diff --git a/plugins/network-elements/midonet/src/com/cloud/network/guru/MidoNetGuestNetworkGuru.java b/plugins/network-elements/midonet/src/com/cloud/network/guru/MidoNetGuestNetworkGuru.java
deleted file mode 100644
index 54480e9ddb2..00000000000
--- a/plugins/network-elements/midonet/src/com/cloud/network/guru/MidoNetGuestNetworkGuru.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.cloud.network.guru;
-
-import javax.inject.Inject;
-
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
-
-import com.cloud.dc.DataCenter.NetworkType;
-import com.cloud.deploy.DeployDestination;
-import com.cloud.deploy.DeploymentPlan;
-import com.cloud.exception.InsufficientAddressCapacityException;
-import com.cloud.exception.InsufficientVirtualNetworkCapacityException;
-import com.cloud.network.Network;
-import com.cloud.network.NetworkProfile;
-import com.cloud.network.Networks;
-import com.cloud.network.PhysicalNetwork;
-import com.cloud.network.dao.NetworkVO;
-import com.cloud.network.dao.PhysicalNetworkVO;
-import com.cloud.offering.NetworkOffering;
-import com.cloud.user.Account;
-import com.cloud.user.AccountVO;
-import com.cloud.user.dao.AccountDao;
-import com.cloud.vm.NicProfile;
-import com.cloud.vm.ReservationContext;
-import com.cloud.vm.VirtualMachineProfile;
-
-@Component
-public class MidoNetGuestNetworkGuru extends GuestNetworkGuru {
- private static final Logger s_logger = Logger.getLogger(MidoNetGuestNetworkGuru.class);
-
- @Inject
- AccountDao _accountDao;
-
- public MidoNetGuestNetworkGuru() {
- super();
- _isolationMethods = new PhysicalNetwork.IsolationMethod[] {PhysicalNetwork.IsolationMethod.MIDO};
- }
-
- @Override
- protected boolean canHandle(NetworkOffering offering, NetworkType networkType, PhysicalNetwork physicalNetwork) {
- // This guru handles only Guest Isolated network that supports Source nat service
- if (networkType == NetworkType.Advanced && isMyTrafficType(offering.getTrafficType()) && offering.getGuestType() == Network.GuestType.Isolated &&
- isMyIsolationMethod(physicalNetwork)) {
- return true;
- } else {
- s_logger.trace("We only take care of Guest networks of type " + Network.GuestType.Isolated + " in zone of type " + NetworkType.Advanced +
- " using isolation method MIDO.");
- return false;
- }
- }
-
- @Override
- public Network design(NetworkOffering offering, DeploymentPlan plan, Network userSpecified, Account owner) {
- s_logger.debug("design called");
- // Check if the isolation type of the related physical network is MIDO
- PhysicalNetworkVO physnet = _physicalNetworkDao.findById(plan.getPhysicalNetworkId());
- if (physnet == null || physnet.getIsolationMethods() == null || !physnet.getIsolationMethods().contains("MIDO")) {
- s_logger.debug("Refusing to design this network, the physical isolation type is not MIDO");
- return null;
- }
-
- s_logger.debug("Physical isolation type is MIDO, asking GuestNetworkGuru to design this network");
- NetworkVO networkObject = (NetworkVO)super.design(offering, plan, userSpecified, owner);
- if (networkObject == null) {
- return null;
- }
- // Override the broadcast domain type - do we need to do this?
- networkObject.setBroadcastDomainType(Networks.BroadcastDomainType.Mido);
-
- return networkObject;
- }
-
- @Override
- public Network implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context)
- throws InsufficientVirtualNetworkCapacityException {
- assert (network.getState() == Network.State.Implementing) : "Why are we implementing " + network;
- s_logger.debug("implement called network: " + network.toString());
-
- long dcId = dest.getDataCenter().getId();
-
- //get physical network id
- long physicalNetworkId = _networkModel.findPhysicalNetworkId(dcId, offering.getTags(), offering.getTrafficType());
-
- NetworkVO implemented =
- new NetworkVO(network.getTrafficType(), network.getMode(), network.getBroadcastDomainType(), network.getNetworkOfferingId(), Network.State.Allocated,
- network.getDataCenterId(), physicalNetworkId, offering.getRedundantRouter());
-
- if (network.getGateway() != null) {
- implemented.setGateway(network.getGateway());
- }
-
- if (network.getCidr() != null) {
- implemented.setCidr(network.getCidr());
- }
-
- AccountVO acc = _accountDao.findById(network.getAccountId());
- String accountUUIDStr = acc.getUuid();
- String routerName = "";
- if (network.getVpcId() != null) {
- routerName = "VPC" + String.valueOf(network.getVpcId());
- } else {
- routerName = String.valueOf(network.getId());
- }
-
- String broadcastUriStr = accountUUIDStr + "." + String.valueOf(network.getId()) + ":" + routerName;
-
- implemented.setBroadcastUri(Networks.BroadcastDomainType.Mido.toUri(broadcastUriStr));
- s_logger.debug("Broadcast URI set to " + broadcastUriStr);
-
- return implemented;
- }
-
- @Override
- public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context)
- throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException {
- s_logger.debug("reserve called with network: " + network.toString() + " nic: " + nic.toString() + " vm: " + vm.toString());
-
- super.reserve(nic, network, vm, dest, context);
- }
-
- @Override
- public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) {
- s_logger.debug("release called with nic: " + nic.toString() + " vm: " + vm.toString());
- return super.release(nic, vm, reservationId);
- }
-
- @Override
- public void shutdown(NetworkProfile profile, NetworkOffering offering) {
- s_logger.debug("shutdown called");
-
- super.shutdown(profile, offering);
- }
-
- @Override
- public boolean trash(Network network, NetworkOffering offering) {
- s_logger.debug("trash called with network: " + network.toString());
-
- return super.trash(network, offering);
- }
-}
diff --git a/plugins/network-elements/midonet/src/com/cloud/network/guru/MidoNetPublicNetworkGuru.java b/plugins/network-elements/midonet/src/com/cloud/network/guru/MidoNetPublicNetworkGuru.java
deleted file mode 100644
index 43093a4fd3f..00000000000
--- a/plugins/network-elements/midonet/src/com/cloud/network/guru/MidoNetPublicNetworkGuru.java
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package com.cloud.network.guru;
-
-import java.net.URI;
-
-import javax.inject.Inject;
-
-import org.apache.log4j.Logger;
-
-import com.cloud.dc.DataCenter;
-import com.cloud.dc.Vlan;
-import com.cloud.deploy.DeployDestination;
-import com.cloud.deploy.DeploymentPlan;
-import com.cloud.exception.ConcurrentOperationException;
-import com.cloud.exception.InsufficientAddressCapacityException;
-import com.cloud.exception.InsufficientVirtualNetworkCapacityException;
-import com.cloud.network.IpAddressManager;
-import com.cloud.network.Network;
-import com.cloud.network.NetworkModel;
-import com.cloud.network.NetworkProfile;
-import com.cloud.network.Networks;
-import com.cloud.network.addr.PublicIp;
-import com.cloud.network.dao.IPAddressVO;
-import com.cloud.network.dao.NetworkVO;
-import com.cloud.offering.NetworkOffering;
-import com.cloud.user.Account;
-import com.cloud.user.AccountVO;
-import com.cloud.user.dao.AccountDao;
-import com.cloud.utils.db.DB;
-import com.cloud.utils.db.Transaction;
-import com.cloud.utils.db.TransactionCallbackNoReturn;
-import com.cloud.utils.db.TransactionStatus;
-import com.cloud.utils.exception.CloudRuntimeException;
-import com.cloud.vm.Nic;
-import com.cloud.vm.NicProfile;
-import com.cloud.vm.ReservationContext;
-import com.cloud.vm.VirtualMachine;
-import com.cloud.vm.VirtualMachineProfile;
-
-public class MidoNetPublicNetworkGuru extends PublicNetworkGuru {
- private static final Logger s_logger = Logger.getLogger(MidoNetPublicNetworkGuru.class);
-
- // Inject any stuff we need to use (DAOs etc)
- @Inject
- NetworkModel _networkModel;
- @Inject
- AccountDao _accountDao;
- @Inject
- IpAddressManager _ipAddrMgr;
-
- // Don't need to change traffic type stuff, public is fine
-
- // Only change is to make broadcast domain type Mido
- @Override
- public Network design(NetworkOffering offering, DeploymentPlan plan, Network network, Account owner) {
- s_logger.debug("design called with network: " + network);
- if (!canHandle(offering)) {
- return null;
- }
-
- if (offering.getTrafficType() == Networks.TrafficType.Public) {
- NetworkVO ntwk =
- new NetworkVO(offering.getTrafficType(), Networks.Mode.Static, Networks.BroadcastDomainType.Mido, offering.getId(), Network.State.Allocated,
- plan.getDataCenterId(), plan.getPhysicalNetworkId(), offering.getRedundantRouter());
- return ntwk;
- } else {
- return null;
- }
- }
-
- protected MidoNetPublicNetworkGuru() {
- super();
- }
-
- @Override
- protected void getIp(NicProfile nic, DataCenter dc, VirtualMachineProfile vm, Network network) throws InsufficientVirtualNetworkCapacityException,
- InsufficientAddressCapacityException, ConcurrentOperationException {
- if (nic.getIPv4Address() == null) {
- PublicIp ip = _ipAddrMgr.assignPublicIpAddress(dc.getId(), null, vm.getOwner(), Vlan.VlanType.VirtualNetwork, null, null, false);
- nic.setIPv4Address(ip.getAddress().addr());
-
- nic.setIPv4Gateway(ip.getGateway());
-
- // Set netmask to /24 for now
- // TDO make it /32 and go via router for anything else on the subnet
- nic.setIPv4Netmask("255.255.255.0");
-
- // Make it the default nic so that a default route is set up.
- nic.setDefaultNic(true);
-
- //nic.setIsolationUri(Networks.IsolationType..Mido.toUri(ip.getVlanTag()));
- nic.setBroadcastUri(network.getBroadcastUri());
- //nic.setBroadcastType(Networks.BroadcastDomainType.Vlan);
- nic.setFormat(Networks.AddressFormat.Ip4);
- nic.setReservationId(String.valueOf(ip.getVlanTag()));
- nic.setMacAddress(ip.getMacAddress());
- }
-
- nic.setIPv4Dns1(dc.getDns1());
- nic.setIPv4Dns2(dc.getDns2());
- }
-
- @Override
- public void updateNicProfile(NicProfile profile, Network network) {
- s_logger.debug("updateNicProfile called with network: " + network + " profile: " + profile);
-
- DataCenter dc = _dcDao.findById(network.getDataCenterId());
- if (profile != null) {
- profile.setIPv4Dns1(dc.getDns1());
- profile.setIPv4Dns2(dc.getDns2());
- }
- }
-
- @Override
- public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapacityException,
- InsufficientAddressCapacityException, ConcurrentOperationException {
-
- if (nic == null) {
- nic = new NicProfile(Nic.ReservationStrategy.Create, null, null, null, null);
- }
- s_logger.debug("allocate called with network: " + network + " nic: " + nic + " vm: " + vm);
- DataCenter dc = _dcDao.findById(network.getDataCenterId());
-
- if (nic.getRequestedIPv4() != null) {
- throw new CloudRuntimeException("Does not support custom ip allocation at this time: " + nic);
- }
-
- getIp(nic, dc, vm, network);
-
- if (nic.getIPv4Address() == null) {
- nic.setReservationStrategy(Nic.ReservationStrategy.Start);
- } else if (vm.getVirtualMachine().getType() == VirtualMachine.Type.DomainRouter) {
- nic.setReservationStrategy(Nic.ReservationStrategy.Managed);
- } else {
- nic.setReservationStrategy(Nic.ReservationStrategy.Create);
- }
-
- nic.setBroadcastUri(generateBroadcastUri(network));
-
- return nic;
- }
-
- @Override
- public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context)
- throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException, ConcurrentOperationException {
- s_logger.debug("reserve called with network: " + network + " nic: " + nic + " vm: " + vm);
- if (nic.getIPv4Address() == null) {
- getIp(nic, dest.getDataCenter(), vm, network);
- }
- }
-
- @Override
- public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) {
- s_logger.debug("release called with nic: " + nic + " vm: " + vm);
- return true;
- }
-
- @Override
- public Network implement(Network network, NetworkOffering offering, DeployDestination destination, ReservationContext context)
- throws InsufficientVirtualNetworkCapacityException {
- s_logger.debug("implement called with network: " + network);
- long dcId = destination.getDataCenter().getId();
-
- //get physical network id
- long physicalNetworkId = _networkModel.findPhysicalNetworkId(dcId, offering.getTags(), offering.getTrafficType());
-
- NetworkVO implemented =
- new NetworkVO(network.getTrafficType(), network.getMode(), network.getBroadcastDomainType(), network.getNetworkOfferingId(), Network.State.Allocated,
- network.getDataCenterId(), physicalNetworkId, offering.getRedundantRouter());
-
- if (network.getGateway() != null) {
- implemented.setGateway(network.getGateway());
- }
-
- if (network.getCidr() != null) {
- implemented.setCidr(network.getCidr());
- }
-
- implemented.setBroadcastUri(generateBroadcastUri(network));
-
- return implemented;
-
- }
-
- @Override
- @DB
- public void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm) {
- s_logger.debug("deallocate called with network: " + network + " nic: " + nic + " vm: " + vm);
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("public network deallocate network: networkId: " + nic.getNetworkId() + ", ip: " + nic.getIPv4Address());
- }
-
- final IPAddressVO ip = _ipAddressDao.findByIpAndSourceNetworkId(nic.getNetworkId(), nic.getIPv4Address());
- if (ip != null && nic.getReservationStrategy() != Nic.ReservationStrategy.Managed) {
- Transaction.execute(new TransactionCallbackNoReturn() {
- @Override
- public void doInTransactionWithoutResult(TransactionStatus status) {
- _ipAddrMgr.markIpAsUnavailable(ip.getId());
- _ipAddressDao.unassignIpAddress(ip.getId());
- }
- });
- }
- nic.deallocate();
-
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Deallocated nic: " + nic);
- }
- }
-
- @Override
- public void shutdown(NetworkProfile network, NetworkOffering offering) {
- s_logger.debug("shutdown called with network: " + network);
- }
-
- @Override
- public boolean trash(Network network, NetworkOffering offering) {
- s_logger.debug("trash called with network: " + network);
- return true;
- }
-
- @Override
- public void updateNetworkProfile(NetworkProfile networkProfile) {
- DataCenter dc = _dcDao.findById(networkProfile.getDataCenterId());
- networkProfile.setDns1(dc.getDns1());
- networkProfile.setDns2(dc.getDns2());
- }
-
- private URI generateBroadcastUri(Network network) {
- AccountVO acc = _accountDao.findById(network.getAccountId());
- String accountUUIDStr = acc.getUuid();
- String networkUUIDStr = String.valueOf(network.getId());
- return Networks.BroadcastDomainType.Mido.toUri(accountUUIDStr + "." + networkUUIDStr + ":" + networkUUIDStr);
- }
-
-}
diff --git a/plugins/network-elements/midonet/src/com/cloud/network/resource/MidoNetVifDriver.java b/plugins/network-elements/midonet/src/com/cloud/network/resource/MidoNetVifDriver.java
deleted file mode 100644
index c3185f58158..00000000000
--- a/plugins/network-elements/midonet/src/com/cloud/network/resource/MidoNetVifDriver.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.cloud.network.resource;
-
-import java.util.Map;
-import java.util.UUID;
-
-import javax.naming.ConfigurationException;
-import javax.ws.rs.core.MultivaluedMap;
-
-import org.apache.log4j.Logger;
-import org.libvirt.LibvirtException;
-import org.midonet.client.MidonetApi;
-import org.midonet.client.resource.Bridge;
-import org.midonet.client.resource.BridgePort;
-import org.midonet.client.resource.Host;
-
-import com.sun.jersey.core.util.MultivaluedMapImpl;
-
-import com.cloud.agent.api.to.NicTO;
-import com.cloud.exception.InternalErrorException;
-import com.cloud.hypervisor.kvm.resource.LibvirtVMDef;
-import com.cloud.hypervisor.kvm.resource.VifDriverBase;
-import com.cloud.network.Networks;
-import com.cloud.utils.NumbersUtil;
-import com.cloud.utils.script.OutputInterpreter;
-import com.cloud.utils.script.Script;
-
-public class MidoNetVifDriver extends VifDriverBase {
-
- private static final Logger s_logger = Logger.getLogger(MidoNetVifDriver.class);
- private int _timeout;
- private String _midoApiLocation = "http://localhost:8081/";
- private static final String midoPostfix = "mnet";
-
- @Override
- public void configure(Map<String, Object> params) throws ConfigurationException {
-
- super.configure(params);
-
- String value = (String)params.get("scripts.timeout");
- _timeout = NumbersUtil.parseInt(value, 30 * 60) * 1000;
-
- // Load Midonet API server location
- String midoLoc = (String)params.get("midonet.apiserver.address");
- if (midoLoc != null) {
- _midoApiLocation = midoLoc;
- }
- }
-
- /*
- * Grab our host id in a file written by Midonet, then
- * return a Host.
- */
- private Host getMyHost(MidonetApi api) {
- Script command = new Script("/bin/bash", _timeout);
- command.add("-c");
- command.add("awk -F'=' '{if ($1~/host/) print $2}' /etc/midolman/host_uuid.properties");
-
- OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser();
- command.execute(parser);
- String host_uuid = parser.getLines().split("\\n")[0];
- for (Host host : api.getHosts()) {
- if (host.getId().toString().equals(host_uuid)) {
- return host;
- }
- }
- return null;
- }
-
- /*
- * simple script to add the tap to the host and bring it up.
- */
- private String addTap() {
- OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser();
- Script command = new Script("/bin/bash", _timeout);
- command.add("-c");
- command.add("ip tuntap add mode tap dev '%d" + midoPostfix + "' && ip link | grep " + midoPostfix + " | sort -n | tail -1 | awk -F': ' '{print $2}'");
- command.execute(parser);
- String tapName = parser.getLines().split("\\n")[0];
- command = new Script("/bin/bash", _timeout);
- command.add("-c");
- command.add("ip link set " + tapName + " up");
- command.execute();
- return tapName;
- }
-
- @Override
- public LibvirtVMDef.InterfaceDef plug(NicTO nic, String guestOsType, String nicAdapter) throws InternalErrorException, LibvirtException {
-
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("nic=" + nic);
- }
-
- LibvirtVMDef.InterfaceDef intf = new LibvirtVMDef.InterfaceDef();
-
- String trafficLabel = nic.getName();
-
- if (nic.getBroadcastType() == Networks.BroadcastDomainType.Mido && (nic.getType() == Networks.TrafficType.Guest || nic.getType() == Networks.TrafficType.Public)) {
- /*
- * create the tap.
- */
- String tapName = addTap();
-
- /*
- * grab the tenant id and the network id from the Broadcast URI.
- * We need to pluck the values out of the String. The string
- * should look like "mido://[tenant_id].[bridge_name]"
- */
- MultivaluedMap qNet = new MultivaluedMapImpl();
- String nicAuthority = nic.getBroadcastUri().getAuthority();
- String tenantId = nicAuthority.split("\\.")[0];
- qNet.add("tenant_id", tenantId);
- String url = nicAuthority.split("\\.")[1];
- String netName = url.split(":")[0];
-
- MidonetApi api = new MidonetApi(_midoApiLocation);
- api.enableLogging();
-
- for (Bridge b : api.getBridges(qNet)) {
- if (b.getName().equals(netName)) {
- for (BridgePort p : b.getPorts()) {
- UUID pvif = p.getVifId();
- if (pvif != null && p.getVifId().toString().equals(nic.getUuid())) {
- getMyHost(api).addHostInterfacePort().interfaceName(tapName).portId(p.getId()).create();
- break;
- }
- }
- }
- }
-
- intf.defEthernet(tapName, nic.getMac(), getGuestNicModel(guestOsType, nicAdapter), "");
-
- } else {
- throw new InternalErrorException("Only NICs of BroadcastDomain type Mido are supported by the MidoNetVifDriver");
- }
-
- return intf;
- }
-
- @Override
- public void unplug(LibvirtVMDef.InterfaceDef iface) {
- String netName = iface.getBrName();
-
- if (netName != null && netName.contains(midoPostfix)) {
- Script command = new Script("/bin/bash", _timeout);
- command.add("-c");
- command.add("ip tuntap del " + iface.getBrName() + " mode tap");
- command.execute();
- }
- }
-}
diff --git a/plugins/network-elements/midonet/test/com/cloud/network/element/MidoNetElementTest.java b/plugins/network-elements/midonet/test/com/cloud/network/element/MidoNetElementTest.java
deleted file mode 100644
index 51e2b1b4329..00000000000
--- a/plugins/network-elements/midonet/test/com/cloud/network/element/MidoNetElementTest.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.cloud.network.element;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.UUID;
-
-import org.midonet.client.MidonetApi;
-import org.midonet.client.resource.Bridge;
-import org.midonet.client.resource.BridgePort;
-import org.midonet.client.resource.DhcpHost;
-import org.midonet.client.resource.DhcpSubnet;
-import org.midonet.client.resource.Port;
-import org.midonet.client.resource.ResourceCollection;
-import org.midonet.client.resource.Router;
-import org.midonet.client.resource.RouterPort;
-
-import com.cloud.exception.ConcurrentOperationException;
-import com.cloud.exception.InsufficientCapacityException;
-import com.cloud.exception.ResourceUnavailableException;
-import com.cloud.network.Network;
-import com.cloud.network.Networks;
-import com.cloud.user.AccountVO;
-import com.cloud.user.dao.AccountDao;
-import com.cloud.vm.NicProfile;
-import com.cloud.vm.VirtualMachine;
-import com.cloud.vm.VirtualMachineProfile;
-
-import junit.framework.TestCase;
-
-public class MidoNetElementTest extends TestCase {
-
- /*
- * Test the standard case of addDhcpEntry with no errors.
- */
- public void testAddDhcpEntry() {
-
- //mockMgmt
- MidonetApi api = mock(MidonetApi.class, RETURNS_DEEP_STUBS);
-
- //mockDhcpHost
- DhcpHost mockDhcpHost = mock(DhcpHost.class);
-
- //mockHostCollection
- ResourceCollection<DhcpHost> hosts = new ResourceCollection<DhcpHost>(new ArrayList<DhcpHost>());
-
- //mockDhcpSubnet
- DhcpSubnet mockSub = mock(DhcpSubnet.class);
- when(mockSub.addDhcpHost()).thenReturn(mockDhcpHost);
- when(mockSub.getDhcpHosts()).thenReturn(hosts);
-
- //mockSubnetCollection
- ResourceCollection mockSubnetCollection = mock(ResourceCollection.class);
- when(mockSubnetCollection.get(anyInt())).thenReturn(mockSub);
-
- //mockBridge
- Bridge mockBridge = mock(Bridge.class);
- when(api.addBridge().tenantId(anyString()).name(anyString()).create()).thenReturn(mockBridge);
- when(mockBridge.getDhcpSubnets()).thenReturn(mockSubnetCollection);
-
- //mockRouter
- Router mockRouter = mock(Router.class);
- when(api.addRouter().tenantId(anyString()).name(anyString()).create()).thenReturn(mockRouter);
-
- //mockNetwork
- Network mockNetwork = mock(Network.class);
- when(mockNetwork.getAccountId()).thenReturn((long)1);
- when(mockNetwork.getGateway()).thenReturn("1.2.3.4");
- when(mockNetwork.getCidr()).thenReturn("1.2.3.0/24");
- when(mockNetwork.getId()).thenReturn((long)2);
- when(mockNetwork.getBroadcastDomainType()).thenReturn(Networks.BroadcastDomainType.Mido);
- when(mockNetwork.getTrafficType()).thenReturn(Networks.TrafficType.Guest);
-
- //mockAccountDao
- AccountDao mockAccountDao = mock(AccountDao.class);
- AccountVO mockAccountVO = mock(AccountVO.class);
- when(mockAccountDao.findById(anyLong())).thenReturn(mockAccountVO);
- when(mockAccountVO.getUuid()).thenReturn("1");
-
- //mockNic
- NicProfile mockNic = mock(NicProfile.class);
- when(mockNic.getIPv4Address()).thenReturn("10.10.10.170");
- when(mockNic.getMacAddress()).thenReturn("02:00:73:3e:00:01");
- when(mockNic.getName()).thenReturn("Fake Name");
-
- //mockVm
- @SuppressWarnings("unchecked")
- VirtualMachineProfile mockVm = mock(VirtualMachineProfile.class);
- when(mockVm.getType()).thenReturn(VirtualMachine.Type.User);
-
- MidoNetElement elem = new MidoNetElement();
- elem.setMidonetApi(api);
- elem.setAccountDao(mockAccountDao);
-
- boolean result = false;
- try {
- result = elem.addDhcpEntry(mockNetwork, mockNic, mockVm, null, null);
- } catch (ConcurrentOperationException e) {
- fail(e.getMessage());
- } catch (InsufficientCapacityException e) {
- fail(e.getMessage());
- } catch (ResourceUnavailableException e) {
- fail(e.getMessage());
- }
-
- assertEquals(result, true);
- }
-
- /*
- * Test the standard case of implement with no errors.
- */
- public void testImplement() {
- //mock
- MidonetApi api = mock(MidonetApi.class, RETURNS_DEEP_STUBS);
-
- //mockAccountDao
- AccountDao mockAccountDao = mock(AccountDao.class);
- AccountVO mockAccountVO = mock(AccountVO.class);
- when(mockAccountDao.findById(anyLong())).thenReturn(mockAccountVO);
- when(mockAccountVO.getUuid()).thenReturn("1");
- MidoNetElement elem = new MidoNetElement();
-
- elem.setMidonetApi(api);
- elem.setAccountDao(mockAccountDao);
-
- //mockRPort
- RouterPort mockRPort = mock(RouterPort.class);
- when(mockRPort.getId()).thenReturn(UUID.fromString("550e8400-e29b-41d4-a716-446655440000"));
-
- //mockBPort
- BridgePort mockBPort = mock(BridgePort.class);
- when(mockBPort.link(any(UUID.class))).thenReturn(mockBPort);
-
- //mockPort
- Port mockPort = mock(Port.class);
-
- ResourceCollection<Port> peerPorts = new ResourceCollection<Port>(new ArrayList<Port>());
-
- peerPorts.add(mockPort);
-
- //mockBridge
- Bridge mockBridge = mock(Bridge.class, RETURNS_DEEP_STUBS);
- when(api.addBridge().tenantId(anyString()).name(anyString()).create()).thenReturn(mockBridge);
- when(mockBridge.addInteriorPort().create()).thenReturn(mockBPort);
- when(mockBridge.getPeerPorts()).thenReturn(peerPorts);
-
- //mockRouter
- Router mockRouter = mock(Router.class, RETURNS_DEEP_STUBS);
- when(api.addRouter().tenantId(anyString()).name(anyString()).create()).thenReturn(mockRouter);
- when(mockRouter.addInteriorRouterPort().create()).thenReturn(mockRPort);
-
- //mockNetwork
- Network mockNetwork = mock(Network.class);
- when(mockNetwork.getAccountId()).thenReturn((long)1);
- when(mockNetwork.getGateway()).thenReturn("1.2.3.4");
- when(mockNetwork.getCidr()).thenReturn("1.2.3.0/24");
- when(mockNetwork.getId()).thenReturn((long)2);
- when(mockNetwork.getBroadcastDomainType()).thenReturn(Networks.BroadcastDomainType.Mido);
- when(mockNetwork.getTrafficType()).thenReturn(Networks.TrafficType.Public);
-
- boolean result = false;
- try {
- result = elem.implement(mockNetwork, null, null, null);
- } catch (ConcurrentOperationException e) {
- fail(e.getMessage());
- } catch (InsufficientCapacityException e) {
- fail(e.getMessage());
- } catch (ResourceUnavailableException e) {
- fail(e.getMessage());
- }
-
- assertEquals(result, true);
- }
-}
diff --git a/plugins/network-elements/netscaler/pom.xml b/plugins/network-elements/netscaler/pom.xml
index 9677fc59dc6..a8a7eb1628c 100644
--- a/plugins/network-elements/netscaler/pom.xml
+++ b/plugins/network-elements/netscaler/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
@@ -37,5 +37,10 @@
<artifactId>sdx_nitro</artifactId>
<version>${cs.nitro.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ <version>20090211</version>
+ </dependency>
</dependencies>
</project>
diff --git a/plugins/network-elements/netscaler/resources/META-INF/cloudstack/netscaler/spring-netscaler-context.xml b/plugins/network-elements/netscaler/resources/META-INF/cloudstack/netscaler/spring-netscaler-context.xml
index a75db6b3db8..ae19c92c172 100644
--- a/plugins/network-elements/netscaler/resources/META-INF/cloudstack/netscaler/spring-netscaler-context.xml
+++ b/plugins/network-elements/netscaler/resources/META-INF/cloudstack/netscaler/spring-netscaler-context.xml
@@ -26,10 +26,11 @@
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
>
-
+ <bean id="netScalerServicePackageDaoImpl" class="com.cloud.network.dao.NetScalerServicePackageDaoImpl" />
+ <bean id="netScalerControlCenterDaoImpl" class="com.cloud.network.dao.NetScalerControlCenterDaoImpl" />
<bean id="netScalerPodDaoImpl" class="com.cloud.network.dao.NetScalerPodDaoImpl" />
<bean id="netscalerElement" class="com.cloud.network.element.NetscalerElement" >
<property name="name" value="Netscaler"/>
</bean>
-
+ <bean id="NetScalerVMManager" class="com.cloud.network.vm.NetScalerVMManagerImpl" />
</beans>
diff --git a/plugins/network-elements/netscaler/src/com/cloud/api/commands/DeleteNetscalerControlCenterCmd.java b/plugins/network-elements/netscaler/src/com/cloud/api/commands/DeleteNetscalerControlCenterCmd.java
new file mode 100644
index 00000000000..f572b09ae88
--- /dev/null
+++ b/plugins/network-elements/netscaler/src/com/cloud/api/commands/DeleteNetscalerControlCenterCmd.java
@@ -0,0 +1,95 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package com.cloud.api.commands;
+
+import javax.inject.Inject;
+import javax.persistence.EntityExistsException;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.api.response.NetscalerControlCenterResponse;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.network.element.NetscalerLoadBalancerElementService;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+@APICommand(name = "deleteNetscalerControlCenter", responseObject = SuccessResponse.class, description = "Delete Netscaler Control Center")
+public class DeleteNetscalerControlCenterCmd extends BaseCmd {
+
+ public static final Logger s_logger = Logger.getLogger(DeleteServicePackageOfferingCmd.class.getName());
+ private static final String s_name = "deleteNetscalerControlCenter";
+ @Inject
+ NetscalerLoadBalancerElementService _netsclarLbService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.ID, type = CommandType.STRING, entityType = NetscalerControlCenterResponse.class, required = true, description = "Netscaler Control Center ID")
+ private String ID;
+
+ @Override
+ public void execute() throws ServerApiException, ConcurrentOperationException, EntityExistsException {
+ SuccessResponse response = new SuccessResponse();
+ try {
+ boolean result = _netsclarLbService.deleteNetscalerControlCenter(this);
+ if (response != null && result) {
+ response.setDisplayText("Netscaler Control Center Deleted Successfully");
+ response.setSuccess(result);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ }
+ } catch (CloudRuntimeException runtimeExcp) {
+ response.setDisplayText(runtimeExcp.getMessage());
+ response.setSuccess(false);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ return;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
+ }
+ }
+
+ public String setId(String iD) {
+ return ID = iD;
+ }
+
+ public String getId() {
+ return ID;
+ }
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccount().getId();
+ }
+
+}
diff --git a/plugins/network-elements/netscaler/src/com/cloud/api/commands/DeleteNetscalerLoadBalancerCmd.java b/plugins/network-elements/netscaler/src/com/cloud/api/commands/DeleteNetscalerLoadBalancerCmd.java
index 1baa7b05d54..16990c56251 100644
--- a/plugins/network-elements/netscaler/src/com/cloud/api/commands/DeleteNetscalerLoadBalancerCmd.java
+++ b/plugins/network-elements/netscaler/src/com/cloud/api/commands/DeleteNetscalerLoadBalancerCmd.java
@@ -96,7 +96,7 @@ public String getEventDescription() {
@Override
public String getEventType() {
- return EventTypes.EVENT_LOAD_BALANCER_DELETE;
+ return EventTypes.EVENT_EXTERNAL_NCC_DEVICE_DELETE;
}
@Override
diff --git a/plugins/network-elements/netscaler/src/com/cloud/api/commands/DeleteServicePackageOfferingCmd.java b/plugins/network-elements/netscaler/src/com/cloud/api/commands/DeleteServicePackageOfferingCmd.java
new file mode 100644
index 00000000000..c6fbec18ee3
--- /dev/null
+++ b/plugins/network-elements/netscaler/src/com/cloud/api/commands/DeleteServicePackageOfferingCmd.java
@@ -0,0 +1,92 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package com.cloud.api.commands;
+
+import javax.inject.Inject;
+import javax.persistence.EntityExistsException;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.context.CallContext;
+
+import org.apache.cloudstack.api.response.SuccessResponse;
+
+import com.cloud.api.response.NetScalerServicePackageResponse;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.network.element.NetscalerLoadBalancerElementService;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+@APICommand(name = "deleteServicePackageOffering", responseObject = SuccessResponse.class, description = "Delete Service Package")
+public class DeleteServicePackageOfferingCmd extends BaseCmd {
+
+ public static final Logger s_logger = Logger.getLogger(DeleteServicePackageOfferingCmd.class.getName());
+ private static final String s_name = "deleteServicePackage";
+ @Inject
+ NetscalerLoadBalancerElementService _netsclarLbService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.ID, type = CommandType.STRING, entityType = NetScalerServicePackageResponse.class, required = true, description = "the service offering ID")
+ private String ID;
+
+ @Override
+ public void execute() throws ServerApiException, ConcurrentOperationException, EntityExistsException {
+ SuccessResponse response = new SuccessResponse();
+ try {
+ boolean result = _netsclarLbService.deleteServicePackageOffering(this);
+
+ if (response != null && result) {
+ response.setDisplayText("Deleted Successfully");
+ response.setSuccess(result);
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ }
+ } catch (CloudRuntimeException runtimeExcp) {
+ response.setDisplayText(runtimeExcp.getMessage());
+ response.setSuccess(false);
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ return;
+ } catch (Exception e) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete Service Package due to internal error.");
+ }
+ }
+
+ public String getId() {
+ return ID;
+ }
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccount().getId();
+ }
+
+}
diff --git a/plugins/network-elements/netscaler/src/com/cloud/api/commands/DeployNetscalerVpxCmd.java b/plugins/network-elements/netscaler/src/com/cloud/api/commands/DeployNetscalerVpxCmd.java
new file mode 100644
index 00000000000..8089599d50b
--- /dev/null
+++ b/plugins/network-elements/netscaler/src/com/cloud/api/commands/DeployNetscalerVpxCmd.java
@@ -0,0 +1,148 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.cloud.api.commands;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ACL;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.NetworkResponse;
+import org.apache.cloudstack.api.response.ServiceOfferingResponse;
+import org.apache.cloudstack.api.response.SystemVmResponse;
+import org.apache.cloudstack.api.response.TemplateResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.api.response.NetscalerLoadBalancerResponse;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.element.NetscalerLoadBalancerElementService;
+import com.cloud.user.Account;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.VirtualMachine;
+
+@APICommand(name = "deployNetscalerVpx", responseObject = NetscalerLoadBalancerResponse.class, description = "Creates new NS Vpx",
+ requestHasSensitiveInfo = true, responseHasSensitiveInfo = false)
+public class DeployNetscalerVpxCmd extends BaseAsyncCmd {
+
+ public static final Logger s_logger = Logger.getLogger(DeployNetscalerVpxCmd.class.getName());
+ private static final String s_name = "deployNetscalerVpx";
+ @Inject
+ NetscalerLoadBalancerElementService _netsclarLbService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, required = true, description = "availability zone for the virtual machine")
+ private Long zoneId;
+
+ @ACL
+ @Parameter(name = ApiConstants.SERVICE_OFFERING_ID, type = CommandType.UUID, entityType = ServiceOfferingResponse.class, required = true, description = "the ID of the service offering for the virtual machine")
+ private Long serviceOfferingId;
+
+ @ACL
+ @Parameter(name = ApiConstants.TEMPLATE_ID, type = CommandType.UUID, entityType = TemplateResponse.class, required = true, description = "the ID of the template for the virtual machine")
+ private Long templateId;
+
+ @Parameter(name = ApiConstants.NETWORK_ID,
+ type = CommandType.UUID,
+ entityType = NetworkResponse.class, required=false,
+ description = "The network this ip address should be associated to.")
+ private Long networkId;
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
+ ResourceAllocationException {
+ try {
+ Map<String,Object> resp = _netsclarLbService.deployNetscalerServiceVm(this);
+ if (resp.size() > 0) {
+ SystemVmResponse response = _responseGenerator.createSystemVmResponse((VirtualMachine)resp.get("vm"));
+ response.setGuestVlan((String)resp.get("guestvlan"));
+ response.setPublicVlan((List<String>)resp.get("publicvlan"));
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Fail to start system vm");
+ }
+
+ } catch (InvalidParameterValueException invalidParamExcp) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, invalidParamExcp.getMessage());
+ } catch (CloudRuntimeException runtimeExcp) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeExcp.getMessage());
+ }
+ }
+
+ public Long getServiceOfferingId() {
+ return serviceOfferingId;
+ }
+
+ public Long getTemplateId() {
+ return templateId;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "Adding a netscaler load balancer device";
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_NETSCALER_VM_START;
+ }
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ public Long getZoneId() {
+ return zoneId;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccount().getId();
+ }
+ public Account getAccount(){
+ return _accountService.getActiveAccountById(getEntityOwnerId());
+ }
+ public void getReservationContext() {
+ }
+}
diff --git a/plugins/network-elements/netscaler/src/com/cloud/api/commands/ListNetscalerControlCenterCmd.java b/plugins/network-elements/netscaler/src/com/cloud/api/commands/ListNetscalerControlCenterCmd.java
new file mode 100644
index 00000000000..1ff119a1b79
--- /dev/null
+++ b/plugins/network-elements/netscaler/src/com/cloud/api/commands/ListNetscalerControlCenterCmd.java
@@ -0,0 +1,93 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package com.cloud.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.ListResponse;
+import com.cloud.api.response.NetscalerControlCenterResponse;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.NetScalerControlCenterVO;
+import com.cloud.network.element.NetscalerLoadBalancerElementService;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+@APICommand(name = "listNetscalerControlCenter", responseObject = NetscalerControlCenterResponse.class, description = "list control center", requestHasSensitiveInfo = true, responseHasSensitiveInfo = false)
+public class ListNetscalerControlCenterCmd extends BaseListCmd {
+
+ public static final Logger s_logger = Logger.getLogger(ListNetscalerControlCenterCmd.class.getName());
+ private static final String s_name = "listNetscalerControlCenter";
+
+ @Inject
+ NetscalerLoadBalancerElementService _netsclarLbService;
+
+ public static String getsName() {
+ return s_name;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException,
+ ConcurrentOperationException, ResourceAllocationException {
+ try {
+ List<NetScalerControlCenterVO> lncCenters = _netsclarLbService.listNetscalerControlCenter(this);
+ if (lncCenters != null) {
+ ListResponse<NetscalerControlCenterResponse> response = new ListResponse<NetscalerControlCenterResponse>();
+ List<NetscalerControlCenterResponse> lncCentersResponse = new ArrayList<NetscalerControlCenterResponse>();
+ if (lncCenters != null && !lncCenters.isEmpty()) {
+ for (NetScalerControlCenterVO lncCentersVO : lncCenters) {
+ NetscalerControlCenterResponse lncCentreResponse = _netsclarLbService
+ .createNetscalerControlCenterResponse(lncCentersVO);
+ lncCentersResponse.add(lncCentreResponse);
+ }
+ }
+
+ response.setResponses(lncCentersResponse);
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR,
+ "Failed to list Net scalar Control Center due to some internal error.");
+ }
+ } catch (InvalidParameterValueException invalidParamExcp) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, invalidParamExcp.getMessage());
+ } catch (CloudRuntimeException runtimeExcp) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeExcp.getMessage());
+ }
+ }
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+}
\ No newline at end of file
diff --git a/plugins/network-elements/netscaler/src/com/cloud/api/commands/ListRegisteredServicePackageCmd.java b/plugins/network-elements/netscaler/src/com/cloud/api/commands/ListRegisteredServicePackageCmd.java
new file mode 100644
index 00000000000..6838833ef94
--- /dev/null
+++ b/plugins/network-elements/netscaler/src/com/cloud/api/commands/ListRegisteredServicePackageCmd.java
@@ -0,0 +1,81 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package com.cloud.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.ListResponse;
+
+import com.cloud.api.response.NetScalerServicePackageResponse;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.element.NetscalerLoadBalancerElementService;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.network.NetScalerServicePackageVO;
+
+@APICommand(name = "listRegisteredServicePackages", responseObject = NetScalerServicePackageResponse.class, description = "lists registered service packages", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+public class ListRegisteredServicePackageCmd extends BaseListCmd {
+
+ public static final Logger s_logger = Logger.getLogger(ListRegisteredServicePackageCmd.class.getName());
+ private static final String s_name = "listregisteredservicepackage";
+ @Inject
+ NetscalerLoadBalancerElementService _netsclarLbService;
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException,
+ ConcurrentOperationException, ResourceAllocationException {
+ try {
+ List<NetScalerServicePackageVO> lrsPackages = _netsclarLbService.listRegisteredServicePackages(this);
+ ListResponse<NetScalerServicePackageResponse> response = new ListResponse<NetScalerServicePackageResponse>();
+ List<NetScalerServicePackageResponse> lbDevicesResponse = new ArrayList<NetScalerServicePackageResponse>();
+
+ if (lrsPackages != null && !lrsPackages.isEmpty()) {
+ for (NetScalerServicePackageVO lrsPackageVO : lrsPackages) {
+ NetScalerServicePackageResponse lbdeviceResponse = _netsclarLbService
+ .createRegisteredServicePackageResponse(lrsPackageVO);
+ lbDevicesResponse.add(lbdeviceResponse);
+ }
+ }
+
+ response.setResponses(lbDevicesResponse);
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } catch (InvalidParameterValueException invalidParamExcp) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, invalidParamExcp.getMessage());
+ } catch (CloudRuntimeException runtimeExcp) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeExcp.getMessage());
+ }
+ }
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+}
diff --git a/plugins/network-elements/netscaler/src/com/cloud/api/commands/RegisterNetscalerControlCenterCmd.java b/plugins/network-elements/netscaler/src/com/cloud/api/commands/RegisterNetscalerControlCenterCmd.java
new file mode 100644
index 00000000000..fe98a7a5fba
--- /dev/null
+++ b/plugins/network-elements/netscaler/src/com/cloud/api/commands/RegisterNetscalerControlCenterCmd.java
@@ -0,0 +1,145 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.cloud.api.commands;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.api.response.NetscalerControlCenterResponse;
+import com.cloud.api.response.NetscalerLoadBalancerResponse;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.NetScalerControlCenterVO;
+import com.cloud.network.element.NetscalerLoadBalancerElementService;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+@APICommand(name = "registerNetscalerControlCenter", responseObject = NetscalerLoadBalancerResponse.class, description = "Adds a netscaler control center device",
+ requestHasSensitiveInfo = true, responseHasSensitiveInfo = false)
+public class RegisterNetscalerControlCenterCmd extends BaseAsyncCmd {
+
+ public static final Logger s_logger = Logger.getLogger(RegisterNetscalerControlCenterCmd.class.getName());
+ private static final String s_name = "registernetscalercontrolcenterresponse";
+ @Inject
+ NetscalerLoadBalancerElementService _netsclarLbService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.IP_ADDRESS , type = CommandType.STRING, required = true, description = "URL of the netscaler controlcenter appliance.")
+ private String ipaddress;
+
+ @Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, required = true, description = "Credentials to reach netscaler controlcenter device")
+ private String username;
+
+ @Parameter(name = ApiConstants.PASSWORD, type = CommandType.STRING, required = true, description = "Credentials to reach netscaler controlcenter device")
+ private String password;
+
+ @Parameter(name = ApiConstants.NUM_RETRIES , type = CommandType.INTEGER, required = true, description = "Credentials to reach netscaler controlcenter device")
+ private int numretries;
+
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+
+ public static Logger getsLogger() {
+ return s_logger;
+ }
+
+ public static String getsName() {
+ return s_name;
+ }
+
+ public NetscalerLoadBalancerElementService get_netsclarLbService() {
+ return _netsclarLbService;
+ }
+
+ public String getIpaddress() {
+ return ipaddress;
+ }
+
+ public int getNumretries() {
+ return numretries;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
+ ResourceAllocationException {
+ try {
+ NetScalerControlCenterVO nccVO = _netsclarLbService.registerNetscalerControlCenter(this);
+ if (nccVO != null) {
+ NetscalerControlCenterResponse response = _netsclarLbService.createNetscalerControlCenterResponse(nccVO);
+ response.setObjectName("netscalerloadbalancer");
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add netscaler load balancer due to internal error.");
+ }
+ } catch (InvalidParameterValueException invalidParamExcp) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, invalidParamExcp.getMessage());
+ } catch (CloudRuntimeException runtimeExcp) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeExcp.getMessage());
+ }
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "Adding a Netscaler Control Center Device";
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_EXTERNAL_NCC_DEVICE_ADD;
+ }
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccount().getId();
+ }
+}
\ No newline at end of file
diff --git a/plugins/network-elements/netscaler/src/com/cloud/api/commands/RegisterServicePackageCmd.java b/plugins/network-elements/netscaler/src/com/cloud/api/commands/RegisterServicePackageCmd.java
new file mode 100644
index 00000000000..fdef005e999
--- /dev/null
+++ b/plugins/network-elements/netscaler/src/com/cloud/api/commands/RegisterServicePackageCmd.java
@@ -0,0 +1,95 @@
+//Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package com.cloud.api.commands;
+
+import javax.inject.Inject;
+import javax.persistence.EntityExistsException;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.api.response.NetScalerServicePackageResponse;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.network.element.NetscalerLoadBalancerElementService;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+@APICommand(name = "registerNetscalerServicePackage", responseObject = NetScalerServicePackageResponse.class, description = "Registers NCC Service Package")
+public class RegisterServicePackageCmd extends BaseCmd {
+
+ public static final Logger s_logger = Logger.getLogger(RegisterServicePackageCmd.class.getName());
+ private static final String s_name = "registerNetscalerServicePackage";
+
+ @Inject
+ NetscalerLoadBalancerElementService _netsclarLbService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "Name of the service Package.")
+ private String spName;
+
+ @Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, required = true, description = "Description of Service Package")
+ private String description;
+
+
+ @Override
+ public void execute() throws ServerApiException, ConcurrentOperationException, EntityExistsException {
+ try {
+ NetScalerServicePackageResponse response = _netsclarLbService.registerNetscalerServicePackage(this);
+ if (response != null) {
+ response.setObjectName("netscalerservicepackage");
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add Service Package due to internal error.");
+ }
+ } catch (InvalidParameterValueException invalidParamExcp) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, invalidParamExcp.getMessage());
+ } catch (CloudRuntimeException runtimeExcp) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeExcp.getMessage());
+ } catch (EntityExistsException runtimeExcp) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Service Pacakge Already Exists with Name " + getSpName());
+ }
+
+ }
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccount().getId();
+ }
+
+ public String getSpName() {
+ return spName;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+}
\ No newline at end of file
diff --git a/plugins/network-elements/netscaler/src/com/cloud/api/commands/StopNetScalerVMCmd.java b/plugins/network-elements/netscaler/src/com/cloud/api/commands/StopNetScalerVMCmd.java
new file mode 100644
index 00000000000..af95255da90
--- /dev/null
+++ b/plugins/network-elements/netscaler/src/com/cloud/api/commands/StopNetScalerVMCmd.java
@@ -0,0 +1,132 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.api.commands;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.acl.SecurityChecker.AccessType;
+import org.apache.cloudstack.api.ACL;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.DomainRouterResponse;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.element.NetscalerLoadBalancerElementService;
+import com.cloud.network.router.VirtualRouter;
+import com.cloud.network.router.VirtualRouter.Role;
+import com.cloud.vm.VirtualMachine;
+
+@APICommand(name = "stopNetScalerVpx", description = "Stops a NetScalervm.", responseObject = DomainRouterResponse.class, entityType = {VirtualMachine.class},
+ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+public class StopNetScalerVMCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(StopNetScalerVMCmd.class.getName());
+ private static final String s_name = "stopNetScalerVmresponse";
+
+ @Inject
+ NetscalerLoadBalancerElementService _netsclarLbService;
+ // ///////////////////////////////////////////////////
+ // ////////////// API parameters /////////////////////
+ // ///////////////////////////////////////////////////
+ @ACL(accessType = AccessType.OperateEntry)
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = DomainRouterResponse.class, required = true, description = "the ID of the NetScaler vm")
+ private Long id;
+
+ @Parameter(name = ApiConstants.FORCED, type = CommandType.BOOLEAN, required = false, description = "Force stop the VM. The caller knows the VM is stopped.")
+ private Boolean forced;
+
+ // ///////////////////////////////////////////////////
+ // ///////////////// Accessors ///////////////////////
+ // ///////////////////////////////////////////////////
+
+ public Long getId() {
+ return id;
+ }
+
+ // ///////////////////////////////////////////////////
+ // ///////////// API Implementation///////////////////
+ // ///////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ VirtualRouter vm = _entityMgr.findById(VirtualRouter.class, getId());
+ if (vm != null && vm.getRole() == Role.NETSCALER_VM) {
+ return vm.getAccountId();
+ } else {
+ throw new InvalidParameterValueException("Unable to find NetScaler vm by id");
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_NETSCALER_VM_STOP;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "stopping Netscaler vm: " + getId();
+ }
+
+ @Override
+ public ApiCommandJobType getInstanceType() {
+ return ApiCommandJobType.DomainRouter;
+ }
+
+ @Override
+ public Long getInstanceId() {
+ return getId();
+ }
+
+ public boolean isForced() {
+ return (forced != null) ? forced : false;
+ }
+
+ @Override
+ public void execute() throws ConcurrentOperationException, ResourceUnavailableException {
+ CallContext.current().setEventDetails("NetScaler vm Id: " + getId());
+ VirtualRouter result = null;
+ VirtualRouter vm = _routerService.findRouter(getId());
+ if (vm == null || vm.getRole() != Role.NETSCALER_VM) {
+ throw new InvalidParameterValueException("Can't find NetScaler lb vm by id");
+ } else {
+ result = _netsclarLbService.stopNetscalerServiceVm(getId(), isForced(), CallContext.current().getCallingAccount(), CallContext.current().getCallingUserId());
+ }
+
+ if (result != null) {
+ DomainRouterResponse response = _responseGenerator.createDomainRouterResponse(result);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to stop Netscaler vm");
+ }
+ }
+}
diff --git a/plugins/network-elements/netscaler/src/com/cloud/api/response/NetScalerServicePackageResponse.java b/plugins/network-elements/netscaler/src/com/cloud/api/response/NetScalerServicePackageResponse.java
new file mode 100644
index 00000000000..ccd814bc03e
--- /dev/null
+++ b/plugins/network-elements/netscaler/src/com/cloud/api/response/NetScalerServicePackageResponse.java
@@ -0,0 +1,73 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.cloud.api.response;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseResponse;
+
+import com.cloud.network.NetScalerServicePackageVO;
+import com.cloud.serializer.Param;
+
+public class NetScalerServicePackageResponse extends BaseResponse {
+
+ @SerializedName(ApiConstants.ID)
+ @Param(description = "Service Package UUID")
+ private String id;
+
+ @SerializedName(ApiConstants.NAME)
+ @Param(description = "Service Package Name")
+ private String name;
+
+ @SerializedName(ApiConstants.DESCRIPTION)
+ @Param(description = "Description of Service Package")
+ private String description;
+
+ public NetScalerServicePackageResponse() {
+ }
+
+ public NetScalerServicePackageResponse(NetScalerServicePackageVO servicePackage) {
+ this.id = servicePackage.getUuid();
+ this.name = servicePackage.getName();
+ this.description = servicePackage.getDescription();
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+}
\ No newline at end of file
diff --git a/plugins/network-elements/netscaler/src/com/cloud/api/response/NetscalerControlCenterResponse.java b/plugins/network-elements/netscaler/src/com/cloud/api/response/NetscalerControlCenterResponse.java
new file mode 100644
index 00000000000..b4e4446ca13
--- /dev/null
+++ b/plugins/network-elements/netscaler/src/com/cloud/api/response/NetscalerControlCenterResponse.java
@@ -0,0 +1,98 @@
+//Licensed to the Apache Software Foundation (ASF) under one or more
+
+//contributor license agreements. See the NOTICE file distributed with
+//this work for additional information regarding copyright ownership.
+//The ASF licenses this file to You under the Apache License, Version 2.0
+//(the "License"); you may not use this file except in compliance with
+//the License. You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing, software
+//distributed under the License is distributed on an "AS IS" BASIS,
+//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//See the License for the specific language governing permissions and
+//limitations under the License.
+
+package com.cloud.api.response;
+
+import com.google.gson.annotations.SerializedName;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseResponse;
+import com.cloud.network.NetScalerControlCenterVO;
+import com.cloud.serializer.Param;
+
+public class NetscalerControlCenterResponse extends BaseResponse {
+
+ @SerializedName(ApiConstants.ID)
+ @Param(description = "id")
+ private String id;
+
+ @SerializedName(ApiConstants.USERNAME)
+ @Param(description = "username")
+ private String username;
+
+ @SerializedName(ApiConstants.UUID)
+ @Param(description = "uuid")
+ private String uuid;
+
+ @SerializedName(ApiConstants.IP_ADDRESS)
+ @Param(description = "ncc_ip")
+ private String nccip;
+
+ @SerializedName(ApiConstants.NUM_RETRIES)
+ @Param(description = "num_retries")
+ private String numretries;
+
+ public NetscalerControlCenterResponse() {
+ }
+
+ public NetscalerControlCenterResponse(NetScalerControlCenterVO controlcenter) {
+ this.id = controlcenter.getUuid();
+ this.username = controlcenter.getUsername();
+ this.uuid = controlcenter.getUuid();
+ this.username = controlcenter.getUsername();
+ this.nccip = controlcenter.getNccip();
+ this.numretries = String.valueOf(controlcenter.getNumRetries());
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
+ public String getNccip() {
+ return nccip;
+ }
+
+ public void setNccip(String nccip) {
+ this.nccip = nccip;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getNumRetries() {
+ return numretries;
+ }
+
+ public void setNumRetries(String numRetries) {
+ this.numretries = numRetries;
+ }
+}
diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/NetScalerControlCenterVO.java b/plugins/network-elements/netscaler/src/com/cloud/network/NetScalerControlCenterVO.java
new file mode 100644
index 00000000000..e9d4ef51ce8
--- /dev/null
+++ b/plugins/network-elements/netscaler/src/com/cloud/network/NetScalerControlCenterVO.java
@@ -0,0 +1,127 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.network;
+
+import java.util.UUID;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.apache.cloudstack.api.InternalIdentity;
+
+
+/**
+ * NetScalerControlCenterVO contains information about a NetScaler Control Center(NCC) such as Username,
+ * Password used for login, the NCC IP and maximum number of unsuccessful tries a user can make.
+ * By using this information CloudStack can access the NCC.
+ */
+@Entity
+@Table(name = "external_netscaler_controlcenter")
+public class NetScalerControlCenterVO implements InternalIdentity {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private long id;
+
+ @Column(name = "username")
+ private String username;
+
+ @Column(name = "password")
+ private String password;
+
+ @Column(name = "uuid")
+ private String uuid;
+
+ @Column(name = "ncc_ip")
+ private String nccip;
+
+ @Column(name = "num_retries")
+ private int numRetries;
+
+ public NetScalerControlCenterVO() {
+ }
+
+ public NetScalerControlCenterVO(long hostId, String username, String password, String nccip, int retries) {
+ this.username = username;
+ this.password = password;
+ this.uuid = UUID.randomUUID().toString();
+ this.nccip = nccip;
+ this.numRetries = retries;
+ }
+ public NetScalerControlCenterVO(String username, String password, String nccip, int retries) {
+ this.username = username;
+ this.password = password;
+ this.uuid = UUID.randomUUID().toString();
+ this.nccip = nccip;
+ this.numRetries = retries;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public String getNccip() {
+ return nccip;
+ }
+
+ public void setNccip(String nccip) {
+ this.nccip = nccip;
+ }
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public int getNumRetries() {
+ return numRetries;
+ }
+
+ public void setNumRetries(int numRetries) {
+ this.numRetries = numRetries;
+ }
+
+ @Override
+ public long getId() {
+ return id;
+ }
+
+}
diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/NetScalerServicePackageVO.java b/plugins/network-elements/netscaler/src/com/cloud/network/NetScalerServicePackageVO.java
new file mode 100644
index 00000000000..82b3fef8507
--- /dev/null
+++ b/plugins/network-elements/netscaler/src/com/cloud/network/NetScalerServicePackageVO.java
@@ -0,0 +1,105 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.network;
+
+import java.util.UUID;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.apache.cloudstack.api.InternalIdentity;
+
+import com.cloud.api.commands.RegisterServicePackageCmd;
+
+/**
+ * NetScalerServicePackageVO contains information about service packages from NetScaler Control Center(NCC).
+ * By using the service package, CloudStack can choose the kind of NetScaler offering it wants to use.
+ */
+@Entity
+@Table(name = " netscaler_servicepackages")
+public class NetScalerServicePackageVO implements InternalIdentity {
+
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private long id;
+
+ @Column(name = "name")
+ private String name;
+
+ @Column(name = "description")
+ private String description;
+
+ @Column(name = "uuid")
+ private String uuid;
+
+ public NetScalerServicePackageVO() {
+
+ }
+
+
+ public NetScalerServicePackageVO(RegisterServicePackageCmd cmd) {
+ this.name = cmd.getSpName();
+ this.description = cmd.getDescription();
+ this.uuid = UUID.randomUUID().toString();
+ }
+
+ @Override
+ public long getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+
+ public String getDescription() {
+ return description;
+ }
+
+
+ public String getUuid() {
+ return uuid;
+ }
+
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+}
diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/dao/NetScalerControlCenterDao.java b/plugins/network-elements/netscaler/src/com/cloud/network/dao/NetScalerControlCenterDao.java
new file mode 100644
index 00000000000..acf8dce2481
--- /dev/null
+++ b/plugins/network-elements/netscaler/src/com/cloud/network/dao/NetScalerControlCenterDao.java
@@ -0,0 +1,28 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.network.dao;
+
+import java.util.List;
+
+import com.cloud.network.NetScalerControlCenterVO;
+import com.cloud.utils.db.GenericDao;
+
+public interface NetScalerControlCenterDao extends GenericDao<NetScalerControlCenterVO, Long> {
+
+ NetScalerControlCenterVO findByPodId(long podId);
+ List<NetScalerControlCenterVO> listByNetScalerDeviceId(long netscalerDeviceId);
+}
diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/dao/NetScalerControlCenterDaoImpl.java b/plugins/network-elements/netscaler/src/com/cloud/network/dao/NetScalerControlCenterDaoImpl.java
new file mode 100644
index 00000000000..1e4f63df8b4
--- /dev/null
+++ b/plugins/network-elements/netscaler/src/com/cloud/network/dao/NetScalerControlCenterDaoImpl.java
@@ -0,0 +1,41 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.network.dao;
+
+import java.util.List;
+
+import org.springframework.stereotype.Component;
+
+import com.cloud.network.NetScalerControlCenterVO;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.GenericDaoBase;
+
+@Component
+@DB
+public class NetScalerControlCenterDaoImpl extends GenericDaoBase<NetScalerControlCenterVO, Long> implements NetScalerControlCenterDao {
+
+ @Override
+ public NetScalerControlCenterVO findByPodId(long podId) {
+ return null;
+ }
+
+ @Override
+ public List<NetScalerControlCenterVO> listByNetScalerDeviceId(long netscalerDeviceId) {
+ return null;
+ }
+
+}
diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/dao/NetScalerServicePackageDao.java b/plugins/network-elements/netscaler/src/com/cloud/network/dao/NetScalerServicePackageDao.java
new file mode 100644
index 00000000000..73fb2634fa5
--- /dev/null
+++ b/plugins/network-elements/netscaler/src/com/cloud/network/dao/NetScalerServicePackageDao.java
@@ -0,0 +1,31 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.network.dao;
+
+import java.util.List;
+
+import com.cloud.network.NetScalerServicePackageVO;
+import com.cloud.utils.db.GenericDao;
+
+public interface NetScalerServicePackageDao extends GenericDao<NetScalerServicePackageVO, Long> {
+
+ NetScalerServicePackageVO findByPodId(long podId);
+
+ List<NetScalerServicePackageVO> listByNetScalerDeviceId(long netscalerDeviceId);
+
+ public void removeAll();
+}
diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/dao/NetScalerServicePackageDaoImpl.java b/plugins/network-elements/netscaler/src/com/cloud/network/dao/NetScalerServicePackageDaoImpl.java
new file mode 100644
index 00000000000..25d0f4b3e01
--- /dev/null
+++ b/plugins/network-elements/netscaler/src/com/cloud/network/dao/NetScalerServicePackageDaoImpl.java
@@ -0,0 +1,67 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.network.dao;
+
+import java.util.List;
+
+import org.springframework.stereotype.Component;
+
+import com.cloud.network.NetScalerServicePackageVO;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+
+@Component
+@DB
+public class NetScalerServicePackageDaoImpl extends GenericDaoBase<NetScalerServicePackageVO, Long> implements NetScalerServicePackageDao {
+
+ final SearchBuilder<NetScalerServicePackageVO> podIdSearch;
+ final SearchBuilder<NetScalerServicePackageVO> deviceIdSearch;
+
+ protected NetScalerServicePackageDaoImpl() {
+ super();
+
+ podIdSearch = createSearchBuilder();
+ podIdSearch.done();
+
+ deviceIdSearch = createSearchBuilder();
+ deviceIdSearch.done();
+ }
+
+ @Override
+ public NetScalerServicePackageVO findByPodId(long podId) {
+ SearchCriteria<NetScalerServicePackageVO> sc = podIdSearch.create();
+ sc.setParameters("pod_id", podId);
+ return findOneBy(sc);
+ }
+
+ @Override
+ public List<NetScalerServicePackageVO> listByNetScalerDeviceId(long netscalerDeviceId) {
+ SearchCriteria<NetScalerServicePackageVO> sc = deviceIdSearch.create();
+ sc.setParameters("netscalerDeviceId", netscalerDeviceId);
+ return search(sc, null);
+ }
+
+ @Override
+ public void removeAll() {
+ List<NetScalerServicePackageVO> list_NetScalerServicePackageVO = this.listAll();
+ for (NetScalerServicePackageVO row : list_NetScalerServicePackageVO) {
+ this.remove(row.getId());
+ }
+ }
+}
diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java
index dbf6d9a4b69..20417353fcc 100644
--- a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java
+++ b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java
@@ -23,20 +23,28 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.UUID;
import javax.inject.Inject;
+import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
+import org.json.JSONException;
+import org.json.JSONObject;
import com.google.gson.Gson;
import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice;
import org.apache.cloudstack.region.gslb.GslbServiceProvider;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.NetScalerImplementNetworkCommand;
import com.cloud.agent.api.routing.GlobalLoadBalancerConfigCommand;
import com.cloud.agent.api.routing.HealthCheckLBConfigAnswer;
import com.cloud.agent.api.routing.HealthCheckLBConfigCommand;
@@ -48,32 +56,51 @@
import com.cloud.api.ApiDBUtils;
import com.cloud.api.commands.AddNetscalerLoadBalancerCmd;
import com.cloud.api.commands.ConfigureNetscalerLoadBalancerCmd;
+import com.cloud.api.commands.DeleteNetscalerControlCenterCmd;
import com.cloud.api.commands.DeleteNetscalerLoadBalancerCmd;
+import com.cloud.api.commands.DeleteServicePackageOfferingCmd;
+import com.cloud.api.commands.DeployNetscalerVpxCmd;
+import com.cloud.api.commands.ListNetscalerControlCenterCmd;
import com.cloud.api.commands.ListNetscalerLoadBalancerNetworksCmd;
import com.cloud.api.commands.ListNetscalerLoadBalancersCmd;
+import com.cloud.api.commands.ListRegisteredServicePackageCmd;
+import com.cloud.api.commands.RegisterNetscalerControlCenterCmd;
+import com.cloud.api.commands.RegisterServicePackageCmd;
+import com.cloud.api.commands.StopNetScalerVMCmd;
+import com.cloud.api.response.NetScalerServicePackageResponse;
+import com.cloud.api.response.NetscalerControlCenterResponse;
import com.cloud.api.response.NetscalerLoadBalancerResponse;
import com.cloud.configuration.Config;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.dc.DataCenterIpAddressVO;
+import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.DataCenterIpAddressDao;
+import com.cloud.deploy.DataCenterDeployment;
import com.cloud.deploy.DeployDestination;
+import com.cloud.deploy.DeploymentPlan;
+import com.cloud.event.ActionEvent;
+import com.cloud.event.EventTypes;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InsufficientNetworkCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.host.Host;
+import com.cloud.host.Host.Type;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.host.dao.HostDetailsDao;
import com.cloud.network.ExternalLoadBalancerDeviceManager;
import com.cloud.network.ExternalLoadBalancerDeviceManagerImpl;
import com.cloud.network.IpAddress;
+import com.cloud.network.IpAddressManager;
+import com.cloud.network.NetScalerControlCenterVO;
import com.cloud.network.NetScalerPodVO;
+import com.cloud.network.NetScalerServicePackageVO;
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Provider;
@@ -88,7 +115,9 @@
import com.cloud.network.dao.ExternalLoadBalancerDeviceDao;
import com.cloud.network.dao.ExternalLoadBalancerDeviceVO;
import com.cloud.network.dao.ExternalLoadBalancerDeviceVO.LBDeviceState;
+import com.cloud.network.dao.NetScalerControlCenterDao;
import com.cloud.network.dao.NetScalerPodDao;
+import com.cloud.network.dao.NetScalerServicePackageDao;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkExternalLoadBalancerDao;
import com.cloud.network.dao.NetworkExternalLoadBalancerVO;
@@ -98,16 +127,26 @@
import com.cloud.network.dao.PhysicalNetworkVO;
import com.cloud.network.lb.LoadBalancingRule;
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
+import com.cloud.network.resource.NetScalerControlCenterResource;
import com.cloud.network.resource.NetscalerResource;
+import com.cloud.network.router.VirtualRouter;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.LbStickinessMethod;
import com.cloud.network.rules.LbStickinessMethod.StickinessMethodType;
import com.cloud.network.rules.LoadBalancerContainer;
import com.cloud.network.rules.StaticNat;
+import com.cloud.network.vm.NetScalerVMManager;
import com.cloud.offering.NetworkOffering;
+import com.cloud.offerings.dao.NetworkOfferingDao;
+import com.cloud.resource.ResourceManager;
+import com.cloud.resource.ResourceState;
+import com.cloud.resource.ServerResource;
+import com.cloud.user.Account;
import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Transaction;
+import com.cloud.utils.db.TransactionCallback;
import com.cloud.utils.db.TransactionCallbackNoReturn;
import com.cloud.utils.db.TransactionStatus;
import com.cloud.utils.exception.CloudRuntimeException;
@@ -116,8 +155,9 @@
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachineProfile;
-public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl implements LoadBalancingServiceProvider, NetscalerLoadBalancerElementService,
- ExternalLoadBalancerDeviceManager, IpDeployer, StaticNatServiceProvider, GslbServiceProvider {
+public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl
+ implements LoadBalancingServiceProvider, NetscalerLoadBalancerElementService, ExternalLoadBalancerDeviceManager,
+ IpDeployer, StaticNatServiceProvider, GslbServiceProvider {
private static final Logger s_logger = Logger.getLogger(NetscalerElement.class);
public static final AutoScaleCounterType AutoScaleCounterSnmp = new AutoScaleCounterType("snmp");
@@ -140,6 +180,8 @@
@Inject
ExternalLoadBalancerDeviceDao _lbDeviceDao;
@Inject
+ NetScalerControlCenterDao _netscalerControlCenterDao;
+ @Inject
NetworkExternalLoadBalancerDao _networkLBDao;
@Inject
PhysicalNetworkDao _physicalNetworkDao;
@@ -155,54 +197,224 @@
DataCenterIpAddressDao _privateIpAddressDao;
@Inject
ExternalLoadBalancerDeviceDao _externalLoadBalancerDeviceDao;
+ @Inject
+ NetScalerServicePackageDao _netscalerServicePackageDao;
+ @Inject
+ ResourceManager _resourceMgr;
+ @Inject
+ HostDetailsDao _hostDetailDao;
+ @Inject
+ IpAddressManager _ipAddrMgr;
+ @Inject
+ NetworkOrchestrationService _networkService;
+ @Inject
+ NetworkOfferingDao _networkOfferingDao = null;
+ @Inject
+ NetScalerVMManager _netScalerVMManager;
private boolean canHandle(Network config, Service service) {
DataCenter zone = _dcDao.findById(config.getDataCenterId());
- boolean handleInAdvanceZone =
- (zone.getNetworkType() == NetworkType.Advanced && (config.getGuestType() == Network.GuestType.Isolated || config.getGuestType() == Network.GuestType.Shared) && config.getTrafficType() == TrafficType.Guest);
- boolean handleInBasicZone =
- (zone.getNetworkType() == NetworkType.Basic && config.getGuestType() == Network.GuestType.Shared && config.getTrafficType() == TrafficType.Guest);
+ // Create a NCC Resource on Demand for the zone.
+
+ boolean handleInAdvanceZone = (zone.getNetworkType() == NetworkType.Advanced
+ && (config.getGuestType() == Network.GuestType.Isolated
+ || config.getGuestType() == Network.GuestType.Shared)
+ && config.getTrafficType() == TrafficType.Guest);
+ boolean handleInBasicZone = (zone.getNetworkType() == NetworkType.Basic
+ && config.getGuestType() == Network.GuestType.Shared && config.getTrafficType() == TrafficType.Guest);
if (!(handleInAdvanceZone || handleInBasicZone)) {
- s_logger.trace("Not handling network with Type " + config.getGuestType() + " and traffic type " + config.getTrafficType() + " in zone of type " +
- zone.getNetworkType());
+ s_logger.trace("Not handling network with Type " + config.getGuestType() + " and traffic type "
+ + config.getTrafficType() + " in zone of type " + zone.getNetworkType());
return false;
}
- return (_networkManager.isProviderForNetwork(getProvider(), config.getId()) && _ntwkSrvcDao.canProviderSupportServiceInNetwork(config.getId(), service,
- Network.Provider.Netscaler));
+ return (_networkManager.isProviderForNetwork(getProvider(), config.getId()) && _ntwkSrvcDao
+ .canProviderSupportServiceInNetwork(config.getId(), service, Network.Provider.Netscaler));
}
private boolean isBasicZoneNetwok(Network config) {
DataCenter zone = _dcDao.findById(config.getDataCenterId());
- return (zone.getNetworkType() == NetworkType.Basic && config.getGuestType() == Network.GuestType.Shared && config.getTrafficType() == TrafficType.Guest);
+ return (zone.getNetworkType() == NetworkType.Basic && config.getGuestType() == Network.GuestType.Shared
+ && config.getTrafficType() == TrafficType.Guest);
}
@Override
- public boolean implement(Network guestConfig, NetworkOffering offering, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException,
- ConcurrentOperationException, InsufficientNetworkCapacityException {
+ public boolean implement(Network guestConfig, NetworkOffering offering, DeployDestination dest,
+ ReservationContext context) throws ResourceUnavailableException, ConcurrentOperationException,
+ InsufficientNetworkCapacityException {
if (!canHandle(guestConfig, Service.Lb)) {
return false;
}
- if (_ntwkSrvcDao.canProviderSupportServiceInNetwork(guestConfig.getId(), Service.StaticNat, Network.Provider.Netscaler) && !isBasicZoneNetwok(guestConfig)) {
- s_logger.error("NetScaler provider can not be Static Nat service provider for the network " + guestConfig.getGuestType() + " and traffic type " +
- guestConfig.getTrafficType());
+ if (_ntwkSrvcDao.canProviderSupportServiceInNetwork(guestConfig.getId(), Service.StaticNat,
+ Network.Provider.Netscaler) && !isBasicZoneNetwok(guestConfig)) {
+ s_logger.error("NetScaler provider can not be Static Nat service provider for the network "
+ + guestConfig.getGuestType() + " and traffic type " + guestConfig.getTrafficType());
return false;
}
try {
- return manageGuestNetworkWithExternalLoadBalancer(true, guestConfig);
+ if (offering.getServicePackage() == null) {
+ return manageGuestNetworkWithExternalLoadBalancer(true, guestConfig);
+ } else {
+ // if the network offering has service package implement it with
+ // Netscaler Control Center
+ return manageGuestNetworkWithNetscalerControlCenter(true, guestConfig, offering);
+ }
} catch (InsufficientCapacityException capacityException) {
- throw new ResourceUnavailableException("There are no NetScaler load balancer devices with the free capacity for implementing this network", DataCenter.class,
- guestConfig.getDataCenterId());
+ throw new ResourceUnavailableException(
+ "There are no NetScaler load balancer devices with the free capacity for implementing this network",
+ DataCenter.class, guestConfig.getDataCenterId());
+ } catch (ConfigurationException e) {
+ throw new ResourceUnavailableException(
+ "There are no NetScaler load balancer devices with the free capacity for implementing this network : "
+ + e.getMessage(),
+ DataCenter.class, guestConfig.getDataCenterId());
}
}
@Override
- public boolean prepare(Network config, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context)
- throws ConcurrentOperationException, InsufficientNetworkCapacityException, ResourceUnavailableException {
+ public HostVO getNetScalerControlCenterForNetwork(Network guestConfig) {
+ long zoneId = guestConfig.getDataCenterId();
+ return _hostDao.findByTypeNameAndZoneId(zoneId, "NetscalerControlCenter", Type.NetScalerControlCenter);
+ }
+
+ public HostVO allocateNCCResourceForNetwork(Network guestConfig) throws ConfigurationException {
+
+ Map<String, String> _configs;
+ List<NetScalerControlCenterVO> ncc = _netscalerControlCenterDao.listAll();
+ HostVO hostVO = null;
+ Map<String, Object> params;
+ if (ncc.size() > 0) {
+ NetScalerControlCenterVO nccVO = ncc.get(0);
+ String ipAddress = nccVO.getNccip();
+ Map hostDetails = new HashMap<String, String>();
+ String hostName = "NetscalerControlCenter";
+ hostDetails.put("name", hostName);
+ hostDetails.put("guid", UUID.randomUUID().toString());
+ hostDetails.put("zoneId", Long.toString(guestConfig.getDataCenterId()));
+ hostDetails.put("ip", ipAddress);
+ hostDetails.put("username", nccVO.getUsername());
+ hostDetails.put("password", DBEncryptionUtil.decrypt(nccVO.getPassword()));
+ hostDetails.put("deviceName", "netscaler control center");
+ hostDetails.put("cmdTimeOut", Long.toString(NumbersUtil.parseInt(_configDao.getValue(Config.NCCCmdTimeOut.key()), 600000)));
+ ServerResource resource = new NetScalerControlCenterResource();
+ resource.configure(hostName, hostDetails);
+ final Host host = _resourceMgr.addHost(guestConfig.getDataCenterId(), resource, Host.Type.NetScalerControlCenter, hostDetails);
+ hostVO = _hostDao.findById(host.getId());
+ }
+ return hostVO;
+ }
+
+ public boolean manageGuestNetworkWithNetscalerControlCenter(boolean add, Network guestConfig,
+ NetworkOffering offering)
+ throws ResourceUnavailableException, InsufficientCapacityException, ConfigurationException {
+
+ if (guestConfig.getTrafficType() != TrafficType.Guest) {
+ s_logger.trace("External load balancer can only be used for guest networks.");
+ return false;
+ }
+
+ long zoneId = guestConfig.getDataCenterId();
+ DataCenterVO zone = _dcDao.findById(zoneId);
+ HostVO netscalerControlCenter = null;
+
+ if (add) {
+ HostVO lbDeviceVO = null;
+ // on restart network, device could have been allocated already,
+ // skip allocation if a device is assigned
+ lbDeviceVO = getNetScalerControlCenterForNetwork(guestConfig);
+ if (lbDeviceVO == null) {
+ // allocate a load balancer device for the network
+ lbDeviceVO = allocateNCCResourceForNetwork(guestConfig);
+ if (lbDeviceVO == null) {
+ String msg = "failed to allocate Netscaler ControlCenter Resource for the zone in the network "
+ + guestConfig.getId();
+ s_logger.error(msg);
+ throw new InsufficientNetworkCapacityException(msg, DataCenter.class,
+ guestConfig.getDataCenterId());
+ }
+ }
+ netscalerControlCenter = _hostDao.findById(lbDeviceVO.getId());
+ s_logger.debug("Allocated Netscaler Control Center device:" + lbDeviceVO.getId() + " for the network: "
+ + guestConfig.getId());
+ } else {
+ // find the load balancer device allocated for the network
+
+ HostVO lbDeviceVO = null;
+ // on restart network, device could have been allocated already, skip allocation if a device is assigned
+ lbDeviceVO = getNetScalerControlCenterForNetwork(guestConfig);
+ if (lbDeviceVO == null) {
+ s_logger.warn(
+ "Network shutdwon requested on external load balancer element, which did not implement the network."
+ + " Either network implement failed half way through or already network shutdown is completed. So just returning.");
+ return true;
+ }
+
+ netscalerControlCenter = _hostDao.findById(lbDeviceVO.getId());
+ assert(netscalerControlCenter != null) : "There is no device assigned to this network how did shutdown network ended up here??";
+ }
+ JSONObject networkDetails = new JSONObject();
+ JSONObject networkPayload = new JSONObject();
+
+ String selfIp = null;
+ try {
+ networkDetails.put("id", guestConfig.getId());
+ networkDetails.put("vlan", guestConfig.getBroadcastUri());
+ networkDetails.put("cidr", guestConfig.getCidr());
+ networkDetails.put("gateway", guestConfig.getGateway());
+ networkDetails.put("servicepackage_id", offering.getServicePackage());
+ networkDetails.put("zone_id", zone.getUuid());
+ networkDetails.put("account_id", guestConfig.getAccountId());
+ networkDetails.put("add", Boolean.toString(add));
+ selfIp = _ipAddrMgr.acquireGuestIpAddress(guestConfig, null);
+ if (selfIp == null) {
+ String msg = "failed to acquire guest IP address so not implementing the network on the NetscalerControlCenter";
+ s_logger.error(msg);
+ throw new InsufficientNetworkCapacityException(msg, Network.class, guestConfig.getId());
+ }
+ networkDetails.put("snip", selfIp);
+ // TODO region is hardcoded make it dynamic
+ networkDetails.put("region_id", 1);
+ networkDetails.put("name", guestConfig.getName());
+ networkPayload.put("network", networkDetails);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+
+ NetScalerImplementNetworkCommand cmd = new NetScalerImplementNetworkCommand(zone.getUuid(), netscalerControlCenter.getId(), networkPayload.toString());
+ Answer answer = _agentMgr.easySend(netscalerControlCenter.getId(), cmd);
+ if (add) {
+ //TODO After getting the answer check with the job id and do poll on the job and then save the selfip or acquired guest ip to the Nics table
+ if (answer != null) {
+ if (answer.getResult() == true) {
+ if (add) {
+ // Insert a new NIC for this guest network to reserve the self IP
+ _networkService.savePlaceholderNic(guestConfig, selfIp, null, null);
+ }
+ } else {
+ return false;
+ }
+ }
+ } else {
+ if (answer != null) {
+ if (answer.getResult() == true) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean prepare(Network config, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest,
+ ReservationContext context) throws ConcurrentOperationException, InsufficientNetworkCapacityException,
+ ResourceUnavailableException {
return true;
}
@@ -212,17 +424,29 @@ public boolean release(Network config, NicProfile nic, VirtualMachineProfile vm,
}
@Override
- public boolean shutdown(Network guestConfig, ReservationContext context, boolean cleanup) throws ResourceUnavailableException, ConcurrentOperationException {
+ public boolean shutdown(Network guestConfig, ReservationContext context, boolean cleanup)
+ throws ResourceUnavailableException, ConcurrentOperationException {
if (!canHandle(guestConfig, Service.Lb)) {
return false;
}
try {
- return manageGuestNetworkWithExternalLoadBalancer(false, guestConfig);
+
+ NetworkOffering networkOffering = _networkOfferingDao.findById(guestConfig.getNetworkOfferingId());
+ if (networkOffering.getServicePackage() == null) {
+ return manageGuestNetworkWithExternalLoadBalancer(true, guestConfig);
+ } else {
+ // if the network offering has service package implement it with Netscaler Control Center
+ return manageGuestNetworkWithNetscalerControlCenter(false, guestConfig, networkOffering);
+ }
} catch (InsufficientCapacityException capacityException) {
- // TODO: handle out of capacity exception gracefully in case of multple providers available
+ // TODO: handle out of capacity exception gracefully in case of
+ // multple providers available
return false;
+ } catch (ConfigurationException e) {
+ e.printStackTrace();
}
+ return false;
}
@Override
@@ -266,27 +490,33 @@ public boolean applyLBRules(Network config, List<LoadBalancingRule> rules) throw
// Specifies that the RoundRobin and Leastconn algorithms are supported for load balancing rules
lbCapabilities.put(Capability.SupportedLBAlgorithms, "roundrobin, leastconn, source");
- // specifies that Netscaler network element can provided both shared and isolation modes
+ // specifies that Netscaler network element can provided both shared and
+ // isolation modes
lbCapabilities.put(Capability.SupportedLBIsolation, "dedicated, shared");
- // Specifies that load balancing rules can be made for either TCP or UDP traffic
- lbCapabilities.put(Capability.SupportedProtocols, "tcp,udp");
+ // Specifies that load balancing rules can be made for either TCP or UDP
+ // traffic
+ lbCapabilities.put(Capability.SupportedProtocols, "tcp,udp,http");
- // Specifies that this element can measure network usage on a per public IP basis
+ // 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
+ // Specifies that load balancing rules can only be made with public IPs
+ // that aren't source NAT IPs
lbCapabilities.put(Capability.LoadBalancingSupportedIps, "additional");
// Supports only Public load balancing
lbCapabilities.put(Capability.LbSchemes, LoadBalancerContainer.Scheme.Public.toString());
// Specifies that load balancing rules can support autoscaling and the list of counters it supports
+ // list of counters it supports
AutoScaleCounter counter;
List<AutoScaleCounter> counterList = new ArrayList<AutoScaleCounter>();
counter = new AutoScaleCounter(AutoScaleCounterSnmp);
counterList.add(counter);
- counter.addParam("snmpcommunity", true, "the community string that has to be used to do a SNMP GET on the AutoScaled Vm", false);
+ counter.addParam("snmpcommunity", true,
+ "the community string that has to be used to do a SNMP GET on the AutoScaled Vm", false);
counter.addParam("snmpport", false, "the port at which SNMP agent is running on the AutoScaled Vm", false);
counter = new AutoScaleCounter(AutoScaleCounterNetscaler);
@@ -298,15 +528,18 @@ public boolean applyLBRules(Network config, List<LoadBalancingRule> rules) throw
LbStickinessMethod method;
List<LbStickinessMethod> methodList = new ArrayList<LbStickinessMethod>();
- method = new LbStickinessMethod(StickinessMethodType.LBCookieBased, "This is cookie based sticky method, can be used only for http");
+ method = new LbStickinessMethod(StickinessMethodType.LBCookieBased,
+ "This is cookie based sticky method, can be used only for http");
methodList.add(method);
method.addParam("holdtime", false, "time period in minutes for which persistence is in effect.", false);
- method = new LbStickinessMethod(StickinessMethodType.AppCookieBased, "This is app session based sticky method, can be used only for http");
+ method = new LbStickinessMethod(StickinessMethodType.AppCookieBased,
+ "This is app session based sticky method, can be used only for http");
methodList.add(method);
method.addParam("name", true, "cookie name passed in http header by apllication to the client", false);
- method = new LbStickinessMethod(StickinessMethodType.SourceBased, "This is source based sticky method, can be used for any type of protocol.");
+ method = new LbStickinessMethod(StickinessMethodType.SourceBased,
+ "This is source based sticky method, can be used for any type of protocol.");
methodList.add(method);
method.addParam("holdtime", false, "time period for which persistence is in effect.", false);
@@ -314,7 +547,7 @@ public boolean applyLBRules(Network config, List<LoadBalancingRule> rules) throw
lbCapabilities.put(Capability.SupportedStickinessMethods, stickyMethodList);
lbCapabilities.put(Capability.ElasticLb, "true");
- //Setting HealthCheck Capability to True for Netscaler element
+ // Setting HealthCheck Capability to True for Netscaler element
lbCapabilities.put(Capability.HealthCheckPolicy, "true");
capabilities.put(Service.Lb, lbCapabilities);
@@ -347,15 +580,15 @@ public ExternalLoadBalancerDeviceVO addNetscalerLoadBalancer(AddNetscalerLoadBal
try {
uri = new URI(cmd.getUrl());
} catch (Exception e) {
- String msg = "Error parsing the url parameter specified in addNetscalerLoadBalancer command due to " + e.getMessage();
+ String msg = "Error parsing the url parameter specified in addNetscalerLoadBalancer command due to "
+ + e.getMessage();
s_logger.debug(msg);
throw new InvalidParameterValueException(msg);
}
Map<String, String> configParams = new HashMap<String, String>();
UrlUtil.parseQueryParameters(uri.getQuery(), false, configParams);
- boolean dedicatedUse =
- (configParams.get(ApiConstants.LOAD_BALANCER_DEVICE_DEDICATED) != null) ? Boolean.parseBoolean(configParams.get(ApiConstants.LOAD_BALANCER_DEVICE_DEDICATED))
- : false;
+ boolean dedicatedUse = (configParams.get(ApiConstants.LOAD_BALANCER_DEVICE_DEDICATED) != null)
+ ? Boolean.parseBoolean(configParams.get(ApiConstants.LOAD_BALANCER_DEVICE_DEDICATED)) : false;
if (dedicatedUse && !deviceName.equals(NetworkDevice.NetscalerVPXLoadBalancer.getName())) {
String msg = "Only Netscaler VPX load balancers can be specified for dedicated use";
@@ -365,7 +598,8 @@ public ExternalLoadBalancerDeviceVO addNetscalerLoadBalancer(AddNetscalerLoadBal
if (cmd.isGslbProvider()) {
- if (!deviceName.equals(NetworkDevice.NetscalerVPXLoadBalancer.getName()) && !deviceName.equals(NetworkDevice.NetscalerMPXLoadBalancer.getName())) {
+ if (!deviceName.equals(NetworkDevice.NetscalerVPXLoadBalancer.getName())
+ && !deviceName.equals(NetworkDevice.NetscalerMPXLoadBalancer.getName())) {
String msg = "Only Netscaler VPX or MPX load balancers can be specified as GSLB service provider";
s_logger.debug(msg);
throw new InvalidParameterValueException(msg);
@@ -378,19 +612,21 @@ public ExternalLoadBalancerDeviceVO addNetscalerLoadBalancer(AddNetscalerLoadBal
}
if (dedicatedUse) {
- throw new InvalidParameterValueException("NetScaler provisioned to be GSLB service provider can only be configured for shared usage.");
+ throw new InvalidParameterValueException(
+ "NetScaler provisioned to be GSLB service provider can only be configured for shared usage.");
}
}
if (cmd.isExclusiveGslbProvider() && !cmd.isGslbProvider()) {
- throw new InvalidParameterValueException("NetScaler can be provisioned to be exclusive GSLB service provider" +
- " only if its being configured as GSLB service provider also.");
+ throw new InvalidParameterValueException(
+ "NetScaler can be provisioned to be exclusive GSLB service provider"
+ + " only if its being configured as GSLB service provider also.");
}
- ExternalLoadBalancerDeviceVO lbDeviceVO =
- addExternalLoadBalancer(cmd.getPhysicalNetworkId(), cmd.getUrl(), cmd.getUsername(), cmd.getPassword(), deviceName, new NetscalerResource(),
- cmd.isGslbProvider(), cmd.isExclusiveGslbProvider(), cmd.getSitePublicIp(), cmd.getSitePrivateIp());
+ ExternalLoadBalancerDeviceVO lbDeviceVO = addExternalLoadBalancer(cmd.getPhysicalNetworkId(), cmd.getUrl(),
+ cmd.getUsername(), cmd.getPassword(), deviceName, new NetscalerResource(), cmd.isGslbProvider(),
+ cmd.isExclusiveGslbProvider(), cmd.getSitePublicIp(), cmd.getSitePrivateIp());
return lbDeviceVO;
}
@@ -421,7 +657,8 @@ public ExternalLoadBalancerDeviceVO configureNetscalerLoadBalancer(ConfigureNets
}
@DB
- private ExternalLoadBalancerDeviceVO configureNetscalerLoadBalancer(final long lbDeviceId, Long capacity, Boolean dedicatedUse, List<Long> newPodsConfig) {
+ private ExternalLoadBalancerDeviceVO configureNetscalerLoadBalancer(final long lbDeviceId, Long capacity,
+ Boolean dedicatedUse, List<Long> newPodsConfig) {
final ExternalLoadBalancerDeviceVO lbDeviceVo = _lbDeviceDao.findById(lbDeviceId);
final Map<String, String> lbDetails = _detailsDao.findDetails(lbDeviceVo.getHostId());
@@ -462,10 +699,11 @@ private ExternalLoadBalancerDeviceVO configureNetscalerLoadBalancer(final long l
String deviceName = lbDeviceVo.getDeviceName();
if (dedicatedUse != null || capacity != null) {
- if (NetworkDevice.NetscalerSDXLoadBalancer.getName().equalsIgnoreCase(deviceName) ||
- NetworkDevice.NetscalerMPXLoadBalancer.getName().equalsIgnoreCase(deviceName)) {
+ if (NetworkDevice.NetscalerSDXLoadBalancer.getName().equalsIgnoreCase(deviceName)
+ || NetworkDevice.NetscalerMPXLoadBalancer.getName().equalsIgnoreCase(deviceName)) {
if (dedicatedUse != null && dedicatedUse == true) {
- throw new InvalidParameterValueException("Netscaler MPX and SDX device should be shared and can not be dedicated to a single account.");
+ throw new InvalidParameterValueException(
+ "Netscaler MPX and SDX device should be shared and can not be dedicated to a single account.");
}
}
@@ -473,11 +711,13 @@ private ExternalLoadBalancerDeviceVO configureNetscalerLoadBalancer(final long l
List<NetworkExternalLoadBalancerVO> networks = _networkLBDao.listByLoadBalancerDeviceId(lbDeviceId);
if ((networks != null) && !networks.isEmpty()) {
if (capacity != null && capacity < networks.size()) {
- throw new CloudRuntimeException("There are more number of networks already using this netscaler device than configured capacity");
+ throw new CloudRuntimeException(
+ "There are more number of networks already using this netscaler device than configured capacity");
}
if (dedicatedUse != null && dedicatedUse == true) {
- throw new CloudRuntimeException("There are networks already using this netscaler device to make device dedicated");
+ throw new CloudRuntimeException(
+ "There are networks already using this netscaler device to make device dedicated");
}
}
}
@@ -528,7 +768,14 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
cmdList.add(DeleteNetscalerLoadBalancerCmd.class);
cmdList.add(ListNetscalerLoadBalancerNetworksCmd.class);
cmdList.add(ListNetscalerLoadBalancersCmd.class);
-
+ cmdList.add(RegisterServicePackageCmd.class);
+ cmdList.add(RegisterNetscalerControlCenterCmd.class);
+ cmdList.add(ListRegisteredServicePackageCmd.class);
+ cmdList.add(ListNetscalerControlCenterCmd.class);
+ cmdList.add(DeleteServicePackageOfferingCmd.class);
+ cmdList.add(DeleteNetscalerControlCenterCmd.class);
+ cmdList.add(DeployNetscalerVpxCmd.class);
+ cmdList.add(StopNetScalerVMCmd.class);
return cmdList;
}
@@ -539,7 +786,8 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
ExternalLoadBalancerDeviceVO lbDeviceVo = _lbDeviceDao.findById(lbDeviceId);
if (lbDeviceVo == null || !isNetscalerDevice(lbDeviceVo.getDeviceName())) {
- throw new InvalidParameterValueException("Could not find Netscaler load balancer device with ID " + lbDeviceId);
+ throw new InvalidParameterValueException(
+ "Could not find Netscaler load balancer device with ID " + lbDeviceId);
}
List<NetworkExternalLoadBalancerVO> networkLbMaps = _networkLBDao.listByLoadBalancerDeviceId(lbDeviceId);
@@ -561,13 +809,15 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
List<ExternalLoadBalancerDeviceVO> lbDevices = new ArrayList<ExternalLoadBalancerDeviceVO>();
if (physcialNetworkId == null && lbDeviceId == null) {
- throw new InvalidParameterValueException("Either physical network Id or load balancer device Id must be specified");
+ throw new InvalidParameterValueException(
+ "Either physical network Id or load balancer device Id must be specified");
}
if (lbDeviceId != null) {
ExternalLoadBalancerDeviceVO lbDeviceVo = _lbDeviceDao.findById(lbDeviceId);
if (lbDeviceVo == null || !isNetscalerDevice(lbDeviceVo.getDeviceName())) {
- throw new InvalidParameterValueException("Could not find Netscaler load balancer device with ID: " + lbDeviceId);
+ throw new InvalidParameterValueException(
+ "Could not find Netscaler load balancer device with ID: " + lbDeviceId);
}
lbDevices.add(lbDeviceVo);
return lbDevices;
@@ -576,7 +826,8 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
if (physcialNetworkId != null) {
pNetwork = _physicalNetworkDao.findById(physcialNetworkId);
if (pNetwork == null) {
- throw new InvalidParameterValueException("Could not find phyical network with ID: " + physcialNetworkId);
+ throw new InvalidParameterValueException(
+ "Could not find phyical network with ID: " + physcialNetworkId);
}
lbDevices = _lbDeviceDao.listByPhysicalNetworkAndProvider(physcialNetworkId, Provider.Netscaler.getName());
return lbDevices;
@@ -585,12 +836,100 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
return null;
}
+ @Override
+ public List<NetScalerServicePackageVO> listRegisteredServicePackages(ListRegisteredServicePackageCmd cmd) {
+
+ List<NetScalerServicePackageVO> lrsPackages = new ArrayList<NetScalerServicePackageVO>();
+ lrsPackages = _netscalerServicePackageDao.listAll();
+ return lrsPackages;
+ }
+
+ @Override
+ public List<NetScalerControlCenterVO> listNetscalerControlCenter(ListNetscalerControlCenterCmd cmd) {
+ return _netscalerControlCenterDao.listAll();
+ }
+
+ @Override
+ public boolean deleteServicePackageOffering(DeleteServicePackageOfferingCmd cmd) throws CloudRuntimeException {
+ NetScalerServicePackageVO result = null;
+ boolean flag=false;
+ try {
+ result = _netscalerServicePackageDao.findByUuid(cmd.getId());
+ if (result == null)
+ throw new CloudRuntimeException("Record does not Exists in the Table");
+
+ if(_networkOfferingDao.isUsingServicePackage(result.getUuid()))
+ {
+ throw new CloudRuntimeException("Network offering is using the service package. First delete the NeworkOffering and then delete ServicePackage");
+ }
+
+ flag = _netscalerServicePackageDao.remove(result.getId());
+
+ } catch (Exception e) {
+ if (e instanceof InvalidParameterValueException)
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, e.getMessage());
+ else
+ throw e;
+
+ }
+ return flag;
+
+ }
+
+ @DB
+ @Override
+ public boolean deleteNetscalerControlCenter(DeleteNetscalerControlCenterCmd cmd) throws CloudRuntimeException {
+
+ NetScalerControlCenterVO result = _netscalerControlCenterDao.findByUuid(cmd.getId());
+ if (result == null)
+ throw new CloudRuntimeException("External Netscaler Control Center Table does not contain record with this ID");
+ else {
+ //ID list of Network Offering which are not removed and have service Package Uuid field not null.
+ List<Long> servicePackageId_list = _networkOfferingDao.listNetworkOfferingID();
+
+ if (servicePackageId_list.size() != 0) {
+ //VO list of Networks which are using Network Offering.
+ List<NetworkVO> networkVO_list = _networkDao.listNetworkVO(servicePackageId_list);
+ if (networkVO_list != null && networkVO_list.size() != 0)
+ throw new CloudRuntimeException(
+ "ServicePackages published by NetScalerControlCenter are being used by NetworkOfferings. Try deleting NetworkOffering with ServicePackages and then delete NetScalerControlCenter.");
+ }
+ }
+ try {
+ _netscalerServicePackageDao.removeAll();
+ } catch (CloudRuntimeException ce) {
+ throw new CloudRuntimeException("Service Package is being used by Network Offering, Try deleting Network Offering and then delete Service Package.");
+ }
+
+ // delete Netscaler Control Center
+ _netscalerControlCenterDao.remove(result.getId());
+
+ //Removal of NCC from Host Table
+ List<HostVO> ncc_list = _hostDao.listAll();
+ if (ncc_list == null) {
+ throw new CloudRuntimeException("Could not find Netscaler Control Center in Database");
+ }
+ for (HostVO ncc : ncc_list) {
+ if (ncc.getType().equals(Host.Type.NetScalerControlCenter)) {
+ try {
+ // put the host in maintenance state in order for it to be deleted
+ ncc.setResourceState(ResourceState.Maintenance);
+ _hostDao.update(ncc.getId(), ncc);
+ _resourceMgr.deleteHost(ncc.getId(), false, false);
+ } catch (Exception e) {
+ s_logger.debug(e);
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
@Override
public NetscalerLoadBalancerResponse createNetscalerLoadBalancerResponse(ExternalLoadBalancerDeviceVO lbDeviceVO) {
NetscalerLoadBalancerResponse response = new NetscalerLoadBalancerResponse();
Host lbHost = _hostDao.findById(lbDeviceVO.getHostId());
Map<String, String> lbDetails = _detailsDao.findDetails(lbDeviceVO.getHostId());
-
response.setId(lbDeviceVO.getUuid());
response.setIpAddress(lbHost.getPrivateIpAddress());
PhysicalNetwork pnw = ApiDBUtils.findPhysicalNetworkById(lbDeviceVO.getPhysicalNetworkId());
@@ -601,7 +940,8 @@ public NetscalerLoadBalancerResponse createNetscalerLoadBalancerResponse(Externa
response.setPrivateInterface(lbDetails.get("privateInterface"));
response.setDeviceName(lbDeviceVO.getDeviceName());
if (lbDeviceVO.getCapacity() == 0) {
- long defaultLbCapacity = NumbersUtil.parseLong(_configDao.getValue(Config.DefaultExternalLoadBalancerCapacity.key()), 50);
+ long defaultLbCapacity = NumbersUtil
+ .parseLong(_configDao.getValue(Config.DefaultExternalLoadBalancerCapacity.key()), 50);
response.setDeviceCapacity(defaultLbCapacity);
} else {
response.setDeviceCapacity(lbDeviceVO.getCapacity());
@@ -627,6 +967,24 @@ public NetscalerLoadBalancerResponse createNetscalerLoadBalancerResponse(Externa
return response;
}
+ @Override
+ public NetscalerControlCenterResponse createNetscalerControlCenterResponse(NetScalerControlCenterVO lncCentersVO) {
+ NetscalerControlCenterResponse response = new NetscalerControlCenterResponse(lncCentersVO);
+ response.setObjectName("netscalercontrolcenter");
+ return response;
+ }
+
+ @Override
+ public NetScalerServicePackageResponse createRegisteredServicePackageResponse(
+ NetScalerServicePackageVO lrsPackageVO) {
+ NetScalerServicePackageResponse response = new NetScalerServicePackageResponse();
+ response.setId(lrsPackageVO.getUuid());
+ response.setName(lrsPackageVO.getName());
+ response.setDescription(lrsPackageVO.getDescription());
+ response.setObjectName("registeredServicepackage");
+ return response;
+ }
+
@Override
public Provider getProvider() {
return Provider.Netscaler;
@@ -634,9 +992,11 @@ public Provider getProvider() {
@Override
public boolean isReady(PhysicalNetworkServiceProvider provider) {
- List<ExternalLoadBalancerDeviceVO> lbDevices = _lbDeviceDao.listByPhysicalNetworkAndProvider(provider.getPhysicalNetworkId(), Provider.Netscaler.getName());
+ List<ExternalLoadBalancerDeviceVO> lbDevices = _lbDeviceDao
+ .listByPhysicalNetworkAndProvider(provider.getPhysicalNetworkId(), Provider.Netscaler.getName());
- // true if at-least one Netscaler device is added in to physical network and is in configured (in enabled state)
+ // true if at-least one Netscaler device is added in to physical network
+ // and is in configured (in enabled state)
// state
if (lbDevices != null && !lbDevices.isEmpty()) {
for (ExternalLoadBalancerDeviceVO lbDevice : lbDevices) {
@@ -645,13 +1005,14 @@ public boolean isReady(PhysicalNetworkServiceProvider provider) {
}
}
}
- return false;
+ return true;
}
@Override
- public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context) throws ConcurrentOperationException,
- ResourceUnavailableException {
- // TODO reset the configuration on all of the netscaler devices in this physical network
+ public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context)
+ throws ConcurrentOperationException, ResourceUnavailableException {
+ // TODO reset the configuration on all of the netscaler devices in this
+ // physical network
return true;
}
@@ -661,9 +1022,9 @@ public boolean canEnableIndividualServices() {
}
private boolean isNetscalerDevice(String deviceName) {
- if ((deviceName == null) ||
- ((!deviceName.equalsIgnoreCase(NetworkDevice.NetscalerMPXLoadBalancer.getName())) &&
- (!deviceName.equalsIgnoreCase(NetworkDevice.NetscalerSDXLoadBalancer.getName())) && (!deviceName.equalsIgnoreCase(NetworkDevice.NetscalerVPXLoadBalancer.getName())))) {
+ if ((deviceName == null) || ((!deviceName.equalsIgnoreCase(NetworkDevice.NetscalerMPXLoadBalancer.getName()))
+ && (!deviceName.equalsIgnoreCase(NetworkDevice.NetscalerSDXLoadBalancer.getName()))
+ && (!deviceName.equalsIgnoreCase(NetworkDevice.NetscalerVPXLoadBalancer.getName())))) {
return false;
} else {
return true;
@@ -678,15 +1039,21 @@ public boolean verifyServicesCombination(Set<Service> services) {
// NetScaler can only act as Lb and Static Nat service provider
if (services != null && !services.isEmpty() && !netscalerServices.containsAll(services)) {
- s_logger.warn("NetScaler network element can only support LB and Static NAT services and service combination " + services + " is not supported.");
+ s_logger.warn(
+ "NetScaler network element can only support LB and Static NAT services and service combination "
+ + services + " is not supported.");
StringBuffer buff = new StringBuffer();
for (Service service : services) {
buff.append(service.getName());
buff.append(" ");
}
- s_logger.warn("NetScaler network element can only support LB and Static NAT services and service combination " + buff.toString() + " is not supported.");
- s_logger.warn("NetScaler network element can only support LB and Static NAT services and service combination " + services + " is not supported.");
+ s_logger.warn(
+ "NetScaler network element can only support LB and Static NAT services and service combination "
+ + buff.toString() + " is not supported.");
+ s_logger.warn(
+ "NetScaler network element can only support LB and Static NAT services and service combination "
+ + services + " is not supported.");
return false;
}
@@ -694,8 +1061,10 @@ public boolean verifyServicesCombination(Set<Service> services) {
}
@Override
- public boolean applyIps(Network network, List<? extends PublicIpAddress> ipAddress, Set<Service> service) throws ResourceUnavailableException {
- // return true, as IP will be associated as part of LB rule configuration
+ public boolean applyIps(Network network, List<? extends PublicIpAddress> ipAddress, Set<Service> service)
+ throws ResourceUnavailableException {
+ // return true, as IP will be associated as part of LB rule
+ // configuration
return true;
}
@@ -709,7 +1078,8 @@ public IpDeployer getIpDeployer(Network network) {
return this;
}
- public boolean applyElasticLoadBalancerRules(Network network, List<LoadBalancingRule> loadBalancingRules) throws ResourceUnavailableException {
+ public boolean applyElasticLoadBalancerRules(Network network, List<LoadBalancingRule> loadBalancingRules)
+ throws ResourceUnavailableException {
if (loadBalancingRules == null || loadBalancingRules.isEmpty()) {
return true;
@@ -721,7 +1091,8 @@ public boolean applyElasticLoadBalancerRules(Network network, List<LoadBalancing
try {
lbDeviceVO = allocateLoadBalancerForNetwork(network);
} catch (Exception e) {
- errMsg = "Could not allocate a NetSclaer load balancer for configuring elastic load balancer rules due to " + e.getMessage();
+ errMsg = "Could not allocate a NetSclaer load balancer for configuring elastic load balancer rules due to "
+ + e.getMessage();
s_logger.error(errMsg);
throw new ResourceUnavailableException(errMsg, this.getClass(), 0);
}
@@ -745,9 +1116,9 @@ public boolean applyElasticLoadBalancerRules(Network network, List<LoadBalancing
List<LbDestination> destinations = rule.getDestinations();
if ((destinations != null && !destinations.isEmpty()) || rule.isAutoScaleConfig()) {
- LoadBalancerTO loadBalancer =
- new LoadBalancerTO(lbUuid, srcIp, srcPort, protocol, algorithm, revoked, false, false, destinations, rule.getStickinessPolicies(),
- rule.getHealthCheckPolicies(), rule.getLbSslCert(), rule.getLbProtocol());
+ LoadBalancerTO loadBalancer = new LoadBalancerTO(lbUuid, srcIp, srcPort, protocol, algorithm, revoked,
+ false, false, destinations, rule.getStickinessPolicies(), rule.getHealthCheckPolicies(),
+ rule.getLbSslCert(), rule.getLbProtocol());
if (rule.isAutoScaleConfig()) {
loadBalancer.setAutoScaleVmGroup(rule.getAutoScaleVmGroup());
}
@@ -757,16 +1128,16 @@ public boolean applyElasticLoadBalancerRules(Network network, List<LoadBalancing
if (loadBalancersToApply.size() > 0) {
int numLoadBalancersForCommand = loadBalancersToApply.size();
- LoadBalancerTO[] loadBalancersForCommand = loadBalancersToApply.toArray(new LoadBalancerTO[numLoadBalancersForCommand]);
+ LoadBalancerTO[] loadBalancersForCommand = loadBalancersToApply
+ .toArray(new LoadBalancerTO[numLoadBalancersForCommand]);
LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(loadBalancersForCommand, null);
HostVO externalLoadBalancer = _hostDao.findById(lbDeviceVO.getHostId());
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 elastic load balancer rules to the external load balancer appliance in zone " + network.getDataCenterId() + " due to: " + details +
- ".";
+ String msg = "Unable to apply elastic load balancer rules to the external load balancer appliance in zone "
+ + network.getDataCenterId() + " due to: " + details + ".";
s_logger.error(msg);
throw new ResourceUnavailableException(msg, DataCenter.class, network.getDataCenterId());
}
@@ -776,13 +1147,15 @@ public boolean applyElasticLoadBalancerRules(Network network, List<LoadBalancing
}
@Override
- public boolean applyStaticNats(Network config, List<? extends StaticNat> rules) throws ResourceUnavailableException {
+ public boolean applyStaticNats(Network config, List<? extends StaticNat> rules)
+ throws ResourceUnavailableException {
if (!canHandle(config, Service.StaticNat)) {
return false;
}
- boolean multiNetScalerDeployment = Boolean.valueOf(_configDao.getValue(Config.EIPWithMultipleNetScalersEnabled.key()));
+ boolean multiNetScalerDeployment = Boolean
+ .valueOf(_configDao.getValue(Config.EIPWithMultipleNetScalersEnabled.key()));
try {
if (!multiNetScalerDeployment) {
@@ -792,7 +1165,8 @@ public boolean applyStaticNats(Network config, List<? extends StaticNat> rules)
try {
lbDevice = allocateLoadBalancerForNetwork(config);
} catch (Exception e) {
- errMsg = "Could not allocate a NetSclaer load balancer for configuring static NAT rules due to" + e.getMessage();
+ errMsg = "Could not allocate a NetSclaer load balancer for configuring static NAT rules due to"
+ + e.getMessage();
s_logger.error(errMsg);
throw new ResourceUnavailableException(errMsg, this.getClass(), 0);
}
@@ -809,8 +1183,8 @@ public boolean applyStaticNats(Network config, List<? extends StaticNat> rules)
rulesTO = new ArrayList<StaticNatRuleTO>();
for (StaticNat rule : rules) {
IpAddress sourceIp = _networkMgr.getIp(rule.getSourceIpAddressId());
- StaticNatRuleTO ruleTO =
- new StaticNatRuleTO(0, sourceIp.getAddress().addr(), null, null, rule.getDestIpAddress(), null, null, null, rule.isForRevoke(), false);
+ StaticNatRuleTO ruleTO = new StaticNatRuleTO(0, sourceIp.getAddress().addr(), null, null,
+ rule.getDestIpAddress(), null, null, null, rule.isForRevoke(), false);
rulesTO.add(ruleTO);
}
}
@@ -828,20 +1202,23 @@ public boolean applyStaticNats(Network config, List<? extends StaticNat> rules)
// validate if EIP rule can be configured.
ExternalLoadBalancerDeviceVO lbDevice = getNetScalerForEIP(rule);
if (lbDevice == null) {
- String errMsg = "There is no NetScaler device configured to perform EIP to guest IP address: " + rule.getDestIpAddress();
+ String errMsg = "There is no NetScaler device configured to perform EIP to guest IP address: "
+ + rule.getDestIpAddress();
s_logger.error(errMsg);
throw new ResourceUnavailableException(errMsg, this.getClass(), 0);
}
List<StaticNatRuleTO> rulesTO = new ArrayList<StaticNatRuleTO>();
IpAddress sourceIp = _networkMgr.getIp(rule.getSourceIpAddressId());
- StaticNatRuleTO ruleTO =
- new StaticNatRuleTO(0, sourceIp.getAddress().addr(), null, null, rule.getDestIpAddress(), null, null, null, rule.isForRevoke(), false);
+ StaticNatRuleTO ruleTO = new StaticNatRuleTO(0, sourceIp.getAddress().addr(), null, null,
+ rule.getDestIpAddress(), null, null, null, rule.isForRevoke(), false);
rulesTO.add(ruleTO);
SetStaticNatRulesCommand cmd = new SetStaticNatRulesCommand(rulesTO, null);
- // send commands to configure INAT rule on the NetScaler device
- SetStaticNatRulesAnswer answer = (SetStaticNatRulesAnswer)_agentMgr.send(lbDevice.getHostId(), cmd);
+ // send commands to configure INAT rule on the NetScaler
+ // device
+ SetStaticNatRulesAnswer answer = (SetStaticNatRulesAnswer)_agentMgr.send(lbDevice.getHostId(),
+ cmd);
if (answer == null) {
String errMsg = "Failed to configure INAT rule on NetScaler device " + lbDevice.getHostId();
s_logger.error(errMsg);
@@ -858,7 +1235,8 @@ public boolean applyStaticNats(Network config, List<? extends StaticNat> rules)
}
}
- // returns configured NetScaler device that is associated with the pod that owns guest IP
+ // returns configured NetScaler device that is associated with the pod that
+ // owns guest IP
private ExternalLoadBalancerDeviceVO getNetScalerForEIP(StaticNat rule) {
String guestIP = rule.getDestIpAddress();
List<DataCenterIpAddressVO> dcGuestIps = _privateIpAddressDao.listAll();
@@ -877,7 +1255,8 @@ private ExternalLoadBalancerDeviceVO getNetScalerForEIP(StaticNat rule) {
return null;
}
- public List<LoadBalancerTO> getElasticLBRulesHealthCheck(Network network, List<LoadBalancingRule> loadBalancingRules) throws ResourceUnavailableException {
+ public List<LoadBalancerTO> getElasticLBRulesHealthCheck(Network network,
+ List<LoadBalancingRule> loadBalancingRules) throws ResourceUnavailableException {
HealthCheckLBConfigAnswer answer = null;
@@ -889,7 +1268,8 @@ private ExternalLoadBalancerDeviceVO getNetScalerForEIP(StaticNat rule) {
ExternalLoadBalancerDeviceVO lbDeviceVO = getExternalLoadBalancerForNetwork(network);
if (lbDeviceVO == null) {
- s_logger.warn("There is no external load balancer device assigned to this network either network is not implement are already shutdown so just returning");
+ s_logger.warn(
+ "There is no external load balancer device assigned to this network either network is not implement are already shutdown so just returning");
return null;
}
@@ -911,17 +1291,18 @@ private ExternalLoadBalancerDeviceVO getNetScalerForEIP(StaticNat rule) {
List<LbDestination> destinations = rule.getDestinations();
if ((destinations != null && !destinations.isEmpty()) || rule.isAutoScaleConfig()) {
- LoadBalancerTO loadBalancer =
- new LoadBalancerTO(lbUuid, srcIp, srcPort, protocol, algorithm, revoked, false, false, destinations, null, rule.getHealthCheckPolicies(),
- rule.getLbSslCert(), rule.getLbProtocol());
+ LoadBalancerTO loadBalancer = new LoadBalancerTO(lbUuid, srcIp, srcPort, protocol, algorithm, revoked,
+ false, false, destinations, null, rule.getHealthCheckPolicies(), rule.getLbSslCert(),
+ rule.getLbProtocol());
loadBalancersToApply.add(loadBalancer);
}
}
if (loadBalancersToApply.size() > 0) {
int numLoadBalancersForCommand = loadBalancersToApply.size();
- LoadBalancerTO[] loadBalancersForCommand = loadBalancersToApply.toArray(new LoadBalancerTO[numLoadBalancersForCommand]);
- HealthCheckLBConfigCommand cmd = new HealthCheckLBConfigCommand(loadBalancersForCommand);
+ LoadBalancerTO[] loadBalancersForCommand = loadBalancersToApply
+ .toArray(new LoadBalancerTO[numLoadBalancersForCommand]);
+ HealthCheckLBConfigCommand cmd = new HealthCheckLBConfigCommand(loadBalancersForCommand, network.getId());
HostVO externalLoadBalancer = _hostDao.findById(lbDeviceVO.getHostId());
answer = (HealthCheckLBConfigAnswer)_agentMgr.easySend(externalLoadBalancer.getId(), cmd);
return answer.getLoadBalancers();
@@ -955,16 +1336,34 @@ public boolean handlesOnlyRulesInTransitionState() {
}
@Override
- public List<LoadBalancerTO> getLBHealthChecks(Network network, List<LoadBalancingRule> rules) throws ResourceUnavailableException {
+ public List<LoadBalancerTO> getLBHealthChecks(Network network, List<LoadBalancingRule> rules)
+ throws ResourceUnavailableException {
return super.getLBHealthChecks(network, rules);
}
@Override
- public boolean applyGlobalLoadBalancerRule(long zoneId, long physicalNetworkId, GlobalLoadBalancerConfigCommand gslbConfigCmd) throws ResourceUnavailableException {
+ public NetScalerServicePackageResponse listNetscalerServicePackage(RegisterServicePackageCmd cmd) {
+ return null;
+ }
+
+ @Override
+ public NetScalerServicePackageResponse deleteNetscalerServicePackage(RegisterServicePackageCmd cmd) {
+ return null;
+ }
+
+ @Override
+ public NetScalerServicePackageResponse createNetscalerServicePackageResponse(NetScalerServicePackageVO servicePackageVO) {
+ return null;
+ }
+
+ @Override
+ public boolean applyGlobalLoadBalancerRule(long zoneId, long physicalNetworkId,
+ GlobalLoadBalancerConfigCommand gslbConfigCmd) throws ResourceUnavailableException {
long zoneGslbProviderHosId = 0;
- // find the NetScaler device configured as gslb service provider in the zone
+ // find the NetScaler device configured as gslb service provider in the
+ // zone
ExternalLoadBalancerDeviceVO nsGslbProvider = findGslbProvider(zoneId, physicalNetworkId);
if (nsGslbProvider == null) {
String msg = "Unable to find a NetScaler configured as gslb service provider in zone " + zoneId;
@@ -972,7 +1371,8 @@ public boolean applyGlobalLoadBalancerRule(long zoneId, long physicalNetworkId,
throw new ResourceUnavailableException(msg, DataCenter.class, zoneId);
}
- // get the host Id corresponding to NetScaler acting as GSLB service provider in the zone
+ // get the host Id corresponding to NetScaler acting as GSLB service
+ // provider in the zone
zoneGslbProviderHosId = nsGslbProvider.getHostId();
// send gslb configuration to NetScaler device
@@ -990,13 +1390,14 @@ private ExternalLoadBalancerDeviceVO findGslbProvider(long zoneId, long physical
List<PhysicalNetworkVO> pNtwks = _physicalNetworkDao.listByZoneAndTrafficType(zoneId, TrafficType.Guest);
if (pNtwks == null || pNtwks.isEmpty()) {
- throw new InvalidParameterValueException("Unable to get physical network: " + physicalNetworkId + " in zone id = " + zoneId);
+ throw new InvalidParameterValueException(
+ "Unable to get physical network: " + physicalNetworkId + " in zone id = " + zoneId);
} else {
for (PhysicalNetwork physicalNetwork : pNtwks) {
if (physicalNetwork.getId() == physicalNetworkId) {
PhysicalNetworkVO physNetwork = pNtwks.get(0);
- ExternalLoadBalancerDeviceVO nsGslbProvider =
- _externalLoadBalancerDeviceDao.findGslbServiceProvider(physNetwork.getId(), Provider.Netscaler.getName());
+ ExternalLoadBalancerDeviceVO nsGslbProvider = _externalLoadBalancerDeviceDao
+ .findGslbServiceProvider(physNetwork.getId(), Provider.Netscaler.getName());
return nsGslbProvider;
}
}
@@ -1009,7 +1410,7 @@ private ExternalLoadBalancerDeviceVO findGslbProvider(long zoneId, long physical
public boolean isServiceEnabledInZone(long zoneId, long physicalNetworkId) {
ExternalLoadBalancerDeviceVO nsGslbProvider = findGslbProvider(zoneId, physicalNetworkId);
- //return true if a NetScaler device is configured in the zone
+ // return true if a NetScaler device is configured in the zone
return (nsGslbProvider != null);
}
@@ -1032,13 +1433,14 @@ public String getZoneGslbProviderPrivateIp(long zoneId, long physicalNetworkId)
}
private boolean canHandleLbRules(List<LoadBalancingRule> rules) {
- Map<Capability, String> lbCaps = this.getCapabilities().get(Service.Lb);
+ Map<Capability, String> lbCaps = getCapabilities().get(Service.Lb);
if (!lbCaps.isEmpty()) {
String schemeCaps = lbCaps.get(Capability.LbSchemes);
if (schemeCaps != null) {
for (LoadBalancingRule rule : rules) {
if (!schemeCaps.contains(rule.getScheme().toString())) {
- s_logger.debug("Scheme " + rules.get(0).getScheme() + " is not supported by the provider " + this.getName());
+ s_logger.debug("Scheme " + rules.get(0).getScheme() + " is not supported by the provider "
+ + getName());
return false;
}
}
@@ -1046,4 +1448,76 @@ private boolean canHandleLbRules(List<LoadBalancingRule> rules) {
}
return true;
}
-}
+
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_NETSCALER_SERVICEPACKAGE_ADD, eventDescription = "Registering NetScaler Service Package")
+ public NetScalerServicePackageResponse registerNetscalerServicePackage(RegisterServicePackageCmd cmd) {
+ NetScalerServicePackageVO servicePackage = new NetScalerServicePackageVO(cmd);
+ NetScalerServicePackageResponse response = null;
+ _netscalerServicePackageDao.persist(servicePackage);
+ response = new NetScalerServicePackageResponse(servicePackage);
+ return response;
+ }
+
+ @Override
+ @DB
+ public NetScalerControlCenterVO registerNetscalerControlCenter(RegisterNetscalerControlCenterCmd cmd) {
+
+ if (_netscalerControlCenterDao.listAll() != null && _netscalerControlCenterDao.listAll().size() != 0)
+ throw new CloudRuntimeException("One Netscaler Control Center already exist in the DataBase. At a time only one Netscaler Control Center is allowed");
+
+ final RegisterNetscalerControlCenterCmd cmdinfo = cmd;
+ String ipAddress = cmd.getIpaddress();
+ Map hostDetails = new HashMap<String, String>();
+ String hostName = "NetscalerControlCenter";
+ hostDetails.put("name", hostName);
+ hostDetails.put("guid", UUID.randomUUID().toString());
+ List<DataCenterVO> dcVO = _dcDao.listEnabledZones();
+ if (dcVO.size() == 0) {
+ throw new CloudRuntimeException("There is no single enabled zone. Please add a zone, enable it and then add Netscaler ControlCenter");
+ }
+ hostDetails.put("zoneId", "1");
+ hostDetails.put("ip", ipAddress);
+ hostDetails.put("username", cmd.getUsername());
+ hostDetails.put("password", cmd.getPassword());
+ hostDetails.put("deviceName", "Netscaler ControlCenter");
+ ServerResource resource = new NetScalerControlCenterResource();
+ try {
+ resource.configure(hostName, hostDetails);
+ return Transaction.execute(new TransactionCallback<NetScalerControlCenterVO>() {
+ @Override
+ public NetScalerControlCenterVO doInTransaction(TransactionStatus status) {
+ NetScalerControlCenterVO nccVO = new NetScalerControlCenterVO(cmdinfo.getUsername(), DBEncryptionUtil.encrypt(cmdinfo.getPassword()),
+ cmdinfo.getIpaddress(), cmdinfo.getNumretries());
+ _netscalerControlCenterDao.persist(nccVO);
+ return nccVO;
+ }
+ });
+ } catch (ConfigurationException e) {
+ resource = null;
+ throw new CloudRuntimeException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Map<String,Object> deployNetscalerServiceVm(DeployNetscalerVpxCmd cmd) {
+ DataCenter zone = _dcDao.findById(cmd.getZoneId());
+ DeployDestination dest = new DeployDestination(zone, null, null, null);
+ Map<String,Object> resp = new HashMap<String, Object>();
+ Long templateId = cmd.getTemplateId();
+ Long serviceOfferingId = cmd.getServiceOfferingId();
+ DeploymentPlan plan = new DataCenterDeployment(dest.getDataCenter().getId());
+ try {
+ resp = _netScalerVMManager.deployNsVpx(cmd.getAccount(), dest, plan, serviceOfferingId, templateId);
+ } catch (InsufficientCapacityException e) {
+ e.printStackTrace();
+ }
+ return resp;
+ }
+
+ @Override
+ public VirtualRouter stopNetscalerServiceVm(Long id, boolean forced, Account callingAccount, long callingUserId) throws ConcurrentOperationException,
+ ResourceUnavailableException {
+ return _netScalerVMManager.stopNetScalerVm(id, forced, callingAccount, callingUserId);
+ }
+}
\ No newline at end of file
diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerLoadBalancerElementService.java b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerLoadBalancerElementService.java
index ea4ab931fb6..308b56d8073 100644
--- a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerLoadBalancerElementService.java
+++ b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerLoadBalancerElementService.java
@@ -17,19 +17,69 @@
package com.cloud.network.element;
import java.util.List;
+import java.util.Map;
import com.cloud.api.commands.AddNetscalerLoadBalancerCmd;
import com.cloud.api.commands.ConfigureNetscalerLoadBalancerCmd;
+import com.cloud.api.commands.DeleteNetscalerControlCenterCmd;
import com.cloud.api.commands.DeleteNetscalerLoadBalancerCmd;
+import com.cloud.api.commands.DeleteServicePackageOfferingCmd;
+import com.cloud.api.commands.DeployNetscalerVpxCmd;
+import com.cloud.api.commands.ListNetscalerControlCenterCmd;
import com.cloud.api.commands.ListNetscalerLoadBalancerNetworksCmd;
import com.cloud.api.commands.ListNetscalerLoadBalancersCmd;
+import com.cloud.api.commands.ListRegisteredServicePackageCmd;
+import com.cloud.api.commands.RegisterNetscalerControlCenterCmd;
+import com.cloud.api.commands.RegisterServicePackageCmd;
+import com.cloud.api.response.NetScalerServicePackageResponse;
+import com.cloud.api.response.NetscalerControlCenterResponse;
import com.cloud.api.response.NetscalerLoadBalancerResponse;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.NetScalerControlCenterVO;
+import com.cloud.network.NetScalerServicePackageVO;
import com.cloud.network.Network;
import com.cloud.network.dao.ExternalLoadBalancerDeviceVO;
+import com.cloud.network.router.VirtualRouter;
+import com.cloud.user.Account;
import com.cloud.utils.component.PluggableService;
+import com.cloud.utils.exception.CloudRuntimeException;
public interface NetscalerLoadBalancerElementService extends PluggableService {
+ /**
+ * lists all Netscaler Control Center user Details
+ * @param ListNetscalerControlCenterCmd
+ * @return list of NetScalerControlCenterVO for Net Scaler Control Center which contains information about user and their network
+ * control center ID etc.
+ *
+ */
+ public List<NetScalerControlCenterVO> listNetscalerControlCenter(ListNetscalerControlCenterCmd cmd);
+
+ /**
+ * Lists all the list Registered Service Packages details in the Network.
+ * @param ListRegisteredServicePackageCmd
+ * @return list of NetScalerServicePackageVO for registered services in the network which contains details of services
+ */
+
+ public List<NetScalerServicePackageVO> listRegisteredServicePackages(ListRegisteredServicePackageCmd cmd);
+
+ /**
+ * Deletes Service Package Offering
+ *
+ * @param DeleteServicePackageOffering
+ * @return boolean value which tells deletion is successful or not.
+ */
+ public boolean deleteServicePackageOffering(DeleteServicePackageOfferingCmd cmd) throws CloudRuntimeException;
+
+ /**
+ * Deletes Netscaler Control Center if it is not in use.
+ *
+ * @param (DeleteNetscalerControlCenter
+ * @return boolean value which tells deletion is successful or not.
+ */
+ public boolean deleteNetscalerControlCenter(DeleteNetscalerControlCenterCmd cmd) throws CloudRuntimeException;
+
/**
* adds a Netscaler load balancer device in to a physical network
* @param AddNetscalerLoadBalancerCmd
@@ -71,4 +121,27 @@
* @return NetscalerLoadBalancerResponse
*/
public NetscalerLoadBalancerResponse createNetscalerLoadBalancerResponse(ExternalLoadBalancerDeviceVO lbDeviceVO);
-}
+
+ /**
+ * creates API response object for netscaler load balancers
+ * @param lbDeviceVO external load balancer VO object
+ * @return NetscalerLoadBalancerResponse
+ */
+ public NetScalerServicePackageResponse registerNetscalerServicePackage(RegisterServicePackageCmd cmd);
+
+ public NetscalerControlCenterResponse createNetscalerControlCenterResponse(NetScalerControlCenterVO lncCentersVO);
+
+ public NetScalerServicePackageResponse createRegisteredServicePackageResponse(NetScalerServicePackageVO lrsPackageVO);
+
+ public NetScalerServicePackageResponse deleteNetscalerServicePackage(RegisterServicePackageCmd cmd);
+
+ public NetScalerServicePackageResponse listNetscalerServicePackage(RegisterServicePackageCmd cmd);
+
+ public NetScalerServicePackageResponse createNetscalerServicePackageResponse(NetScalerServicePackageVO servicePackageVO);
+
+ public NetScalerControlCenterVO registerNetscalerControlCenter(RegisterNetscalerControlCenterCmd registerNetscalerControlCenterCmd);
+
+ public Map<String, Object> deployNetscalerServiceVm(DeployNetscalerVpxCmd cmd);
+
+ public VirtualRouter stopNetscalerServiceVm(Long id, boolean forced, Account callingAccount, long callingUserId) throws ConcurrentOperationException, ResourceUnavailableException;
+}
\ No newline at end of file
diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetScalerControlCenterResource.java b/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetScalerControlCenterResource.java
new file mode 100644
index 00000000000..347186c2cac
--- /dev/null
+++ b/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetScalerControlCenterResource.java
@@ -0,0 +1,924 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.network.resource;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.conn.ssl.TrustStrategy;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.conn.BasicClientConnectionManager;
+import org.apache.http.util.EntityUtils;
+import org.apache.log4j.Logger;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import com.google.gson.Gson;
+
+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.NetScalerImplementNetworkCommand;
+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.UnsupportedAnswer;
+import com.cloud.agent.api.routing.DestroyLoadBalancerApplianceCommand;
+import com.cloud.agent.api.routing.GlobalLoadBalancerConfigCommand;
+import com.cloud.agent.api.routing.HealthCheckLBConfigAnswer;
+import com.cloud.agent.api.routing.HealthCheckLBConfigCommand;
+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.routing.SetStaticNatRulesCommand;
+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.agent.api.to.LoadBalancerTO.StickinessPolicyTO;
+import com.cloud.host.Host;
+import com.cloud.host.Host.Type;
+import com.cloud.network.rules.LbStickinessMethod.StickinessMethodType;
+import com.cloud.resource.ServerResource;
+import com.cloud.serializer.GsonHelper;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.StringUtils;
+import com.cloud.utils.exception.ExecutionException;
+import com.cloud.utils.net.NetUtils;
+
+class NccHttpCode {
+ static final String INTERNAL_ERROR = "INTERNAL ERROR";
+ static final String NOT_FOUND = "NOT FOUND";
+ static final String JOB_ID = "Job_id";
+ static final String UNAUTHORIZED = "UNAUTHORIZED";
+}
+
+public class NetScalerControlCenterResource 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 Long _nccCmdTimeout;
+ private String _guid;
+ private boolean _inline;
+ private String _deviceName;
+ private String _sessionid;
+ public static final int DEFAULT_PORT = 443;
+ private static final Gson s_gson = GsonHelper.getGson();
+ private static final Logger s_logger = Logger.getLogger(NetScalerControlCenterResource.class);
+ protected Gson _gson;
+ private final String _objectNamePathSep = "-";
+ final String protocol="https";
+ private static String nccsession;
+ private int pingCount = 0;
+
+ public NetScalerControlCenterResource() {
+ _gson = GsonHelper.getGsonLogger();
+ }
+
+
+ public static String get_nccsession() {
+ return nccsession;
+ }
+
+
+ public static void set_nccsession(String nccsession) {
+ NetScalerControlCenterResource.nccsession = nccsession;
+ }
+
+
+ @Override
+ public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+ JSONObject jsonResponse = null;
+ try {
+ _name = (String)params.get("name");
+ if (_name == null) {
+ throw new ConfigurationException("Unable to find name in the configuration parameters");
+ }
+
+ _zoneId = (String)params.get("zoneId");
+ if (_zoneId == null) {
+ throw new ConfigurationException("Unable to find zone Id in the configuration parameters");
+ }
+
+ _ip = (String)params.get("ip");
+ if (_ip == null) {
+ throw new ConfigurationException("Unable to find IP address in the configuration parameters");
+ }
+
+ _username = (String)params.get("username");
+ if (_username == null) {
+ throw new ConfigurationException("Unable to find username in the configuration parameters");
+ }
+
+ _password = (String)params.get("password");
+ if (_password == null) {
+ throw new ConfigurationException("Unable to find password in the configuration parameters");
+ }
+
+ _numRetries = NumbersUtil.parseInt((String)params.get("numretries"), 2);
+
+ _guid = (String)params.get("guid");
+ if (_guid == null) {
+ throw new ConfigurationException("Unable to find the guid in the configuration parameters");
+ }
+
+ _deviceName = (String)params.get("deviceName");
+ if (_deviceName == null) {
+ throw new ConfigurationException("Unable to find the device name in the configuration parameters");
+ }
+ _nccCmdTimeout = NumbersUtil.parseLong((String)params.get("numretries"), 600000);
+
+ // validate device configuration parameters
+ login();
+
+ return true;
+ } catch (ConfigurationException e) {
+ throw new ConfigurationException(e.getMessage());
+ } catch (ExecutionException e) {
+ s_logger.debug("Execution Exception :" + e.getMessage());
+ throw new ConfigurationException("Failed to add the device. Please check the device is NCC and It is reachable from Management Server.");
+ }
+ }
+
+ public void getServicePackages() throws ExecutionException {
+ String result = null;
+ try {
+ URI agentUri = null;
+ agentUri =
+ new URI("https", null, _ip, DEFAULT_PORT,
+ "/admin/v1/servicepackages", null, null);
+
+ org.json.JSONObject jsonBody = new JSONObject();
+ org.json.JSONObject jsonCredentials = new JSONObject();
+ result = getHttpRequest(jsonBody.toString(), agentUri, _sessionid);
+ s_logger.debug("List of Service Packages in NCC:: " + result);
+ } catch (URISyntaxException e) {
+ String errMsg = "Could not generate URI for Hyper-V agent";
+ s_logger.error(errMsg, e);
+
+ } catch (Exception e) {
+ throw new ExecutionException("Failed to log in to NCC device at " + _ip + " due to " + e.getMessage());
+ }
+ }
+
+ private synchronized String login() throws ExecutionException{
+ String result = null;
+ JSONObject jsonResponse = null;
+ try {
+ URI agentUri = null;
+ agentUri =
+ new URI("https", null, _ip, DEFAULT_PORT,
+ "/nitro/v2/config/" + "login", null, null);
+ org.json.JSONObject jsonBody = new JSONObject();
+ org.json.JSONObject jsonCredentials = new JSONObject();
+ jsonCredentials.put("username", _username);
+ jsonCredentials.put("password", _password);
+ jsonBody.put("login", jsonCredentials);
+
+ result = postHttpRequest(jsonBody.toString(), agentUri, _sessionid);
+ if (result == null) {
+ throw new ConfigurationException("No Response Received from the NetScalerControlCenter Device");
+ } else {
+ jsonResponse = new JSONObject(result);
+ org.json.JSONArray loginResponse = jsonResponse.getJSONArray("login");
+ _sessionid = jsonResponse.getJSONArray("login").getJSONObject(0).getString("sessionid");
+ s_logger.debug("New Session id from NCC :" + _sessionid);
+ set_nccsession(_sessionid);
+ s_logger.debug("session on Static Session variable" + get_nccsession());
+ }
+ s_logger.debug("Login to NCC Device response :: " + result);
+ return result;
+ } catch (URISyntaxException e) {
+ String errMsg = "Could not generate URI for Hyper-V agent";
+ s_logger.error(errMsg, e);
+
+ } catch (JSONException e) {
+ s_logger.debug("JSON Exception :" + e.getMessage());
+ throw new ExecutionException("Failed to log in to NCC device at " + _ip + " due to " + e.getMessage());
+ } catch (Exception e) {
+ throw new ExecutionException("Failed to log in to NCC device at " + _ip + " due to " + e.getMessage());
+ }
+ return result;
+ }
+
+ @Override
+ public StartupCommand[] initialize() {
+ StartupExternalLoadBalancerCommand cmd = new StartupExternalLoadBalancerCommand(Host.Type.NetScalerControlCenter);
+ cmd.setName(_name);
+ cmd.setDataCenter(_zoneId);
+ cmd.setPod("");
+ cmd.setPrivateIpAddress(_ip);
+ cmd.setStorageIpAddress("");
+ cmd.setVersion(NetScalerControlCenterResource.class.getPackage().getImplementationVersion());
+ 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, numRetries);
+ } else if (cmd instanceof DestroyLoadBalancerApplianceCommand) {
+ return Answer.createUnsupportedCommandAnswer(cmd);
+ } else if (cmd instanceof SetStaticNatRulesCommand) {
+ return execute((SetStaticNatRulesCommand)cmd, numRetries);
+ } else if (cmd instanceof GlobalLoadBalancerConfigCommand) {
+ return Answer.createUnsupportedCommandAnswer(cmd);
+ } else if (cmd instanceof HealthCheckLBConfigCommand) {
+ return execute((HealthCheckLBConfigCommand)cmd, numRetries);
+ } else if (cmd instanceof NetScalerImplementNetworkCommand ) {
+ return execute((NetScalerImplementNetworkCommand)cmd, numRetries);
+ }
+ else {
+ return Answer.createUnsupportedCommandAnswer(cmd);
+ }
+ }
+
+ private Answer execute(ReadyCommand cmd) {
+ return new ReadyAnswer(cmd);
+ }
+
+ protected Answer execute(MaintainCommand cmd) {
+ return new MaintainAnswer(cmd);
+ }
+
+ private void keepSessionAlive() throws ExecutionException {
+ URI agentUri = null;
+ try {
+ agentUri =
+ new URI("https", null, _ip, DEFAULT_PORT,
+ "/cs/cca/v1/cloudstacks", null, null);
+ org.json.JSONObject jsonBody = new JSONObject();
+ getHttpRequest(jsonBody.toString(), agentUri, _sessionid);
+ s_logger.debug("Keeping Session Alive");
+ } catch (URISyntaxException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private String queryAsyncJob(String jobId) throws ExecutionException {
+ String result = null;
+ try {
+ URI agentUri = null;
+ agentUri =
+ new URI("https", null, _ip, DEFAULT_PORT,
+ "/admin/v1/journalcontexts/" + jobId, null, null);
+
+ org.json.JSONObject jsonBody = new JSONObject();
+
+ long startTick = System.currentTimeMillis();
+ while (System.currentTimeMillis() - startTick < _nccCmdTimeout) {
+ result = getHttpRequest(jsonBody.toString(), agentUri, _sessionid);
+ JSONObject response = new JSONObject(result);
+ if(response != null ) {
+ s_logger.debug("Job Status result for ["+jobId + "]:: " + result + " Tick and currentTime :" + System.currentTimeMillis() +" -" + startTick + "job cmd timeout :" +_nccCmdTimeout);
+ String status = response.getJSONObject("journalcontext").getString("status").toUpperCase();
+ String message = response.getJSONObject("journalcontext").getString("message");
+ s_logger.debug("Job Status Progress Status ["+ jobId + "]:: " + status);
+ switch(status) {
+ case "FINISHED":
+ return status;
+ case "IN PROGRESS":
+ break;
+ case "ERROR, ROLLBACK IN PROGRESS":
+ break;
+ case "ERROR, ROLLBACK COMPLETED":
+ throw new ExecutionException("ERROR, ROLLBACK COMPLETED " + message);
+ case "ERROR, ROLLBACK FAILED":
+ throw new ExecutionException("ERROR, ROLLBACK FAILED " + message);
+ }
+ }
+ }
+
+ } catch (URISyntaxException e) {
+ String errMsg = "Could not generate URI for NetScaler ControlCenter";
+ s_logger.error(errMsg, e);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+ private synchronized Answer execute(NetScalerImplementNetworkCommand cmd, int numRetries) {
+ String result = null;
+ try {
+ URI agentUri = null;
+ agentUri =
+ new URI("https", null, _ip, DEFAULT_PORT,
+ "/cs/adcaas/v1/networks", null, null);
+ org.json.JSONObject jsonBody = new JSONObject(cmd.getDetails());
+ s_logger.debug("Sending Network Implement to NCC:: " + jsonBody);
+ result = postHttpRequest(jsonBody.toString(), agentUri, _sessionid);
+ s_logger.debug("Result of Network Implement to NCC:: " + result);
+ result = queryAsyncJob(result);
+ s_logger.debug("Done query async of network implement request :: " + result);
+ return new Answer(cmd, true, "Successfully allocated device");
+ } catch (URISyntaxException e) {
+ String errMsg = "Could not generate URI for NetScaler ControlCenter ";
+ s_logger.error(errMsg, e);
+ } catch (ExecutionException e) {
+ if(e.getMessage().equalsIgnoreCase(NccHttpCode.NOT_FOUND)) {
+ return new Answer(cmd, true, "Successfully unallocated the device");
+ }else if(e.getMessage().startsWith("ERROR, ROLLBACK") ) {
+ s_logger.error(e.getMessage());
+ return new Answer(cmd, false, e.getMessage());
+ }
+ else {
+ if (shouldRetry(numRetries)) {
+ s_logger.debug("Retrying the command NetScalerImplementNetworkCommand retry count: " + numRetries );
+ return retry(cmd, numRetries);
+ } else {
+ return new Answer(cmd, false, e.getMessage());
+ }
+ }
+ } catch (Exception e) {
+ if (shouldRetry(numRetries)) {
+ s_logger.debug("Retrying the command NetScalerImplementNetworkCommand retry count: " + numRetries );
+ return retry(cmd, numRetries);
+ } else {
+ return new Answer(cmd, false, e.getMessage());
+ }
+ }
+
+ return Answer.createUnsupportedCommandAnswer(cmd);
+ }
+
+ private synchronized Answer execute(IpAssocCommand cmd, int numRetries) {
+
+ String[] results = new String[cmd.getIpAddresses().length];
+ int i = 0;
+ IpAddressTO[] ips = cmd.getIpAddresses();
+ for (IpAddressTO ip : ips) {
+ results[i++] = ip.getPublicIp() + " - success";
+ }
+
+ return new IpAssocAnswer(cmd, results);
+ }
+
+ private Answer execute(HealthCheckLBConfigCommand cmd, int numRetries) {
+
+ List<LoadBalancerTO> hcLB = new ArrayList<LoadBalancerTO>();
+ try {
+
+ LoadBalancerTO[] loadBalancers = cmd.getLoadBalancers();
+
+ if (loadBalancers == null) {
+ return new HealthCheckLBConfigAnswer(hcLB);
+ }
+ String result = getLBHealthChecks(cmd.getNetworkId());
+ JSONObject res = new JSONObject(result);
+ JSONArray lbstatus = res.getJSONArray("lbhealthstatus");
+ for(int i=0; i<lbstatus.length(); i++) {
+ JSONObject lbstat = lbstatus.getJSONObject(i);
+ LoadBalancerTO loadBalancer = null;
+ JSONArray dest = lbstat.getJSONArray("destinations");
+ List<DestinationTO> listDestTo = new ArrayList<DestinationTO>();
+ for(int d=0; d<dest.length(); d++ ) {
+ JSONObject dt = dest.getJSONObject(d);
+ if( dt!=null ) {
+ DestinationTO destTO = new DestinationTO(dt.getString("destIp"), dt.getInt("destPort"), dt.getString("monitorState"));
+ listDestTo.add(destTO);
+ }
+ }
+ loadBalancer = new LoadBalancerTO(lbstat.getString("lb_uuid"),listDestTo);
+ hcLB.add(loadBalancer);
+ }
+ } catch (ExecutionException e) {
+ s_logger.error("Failed to execute HealthCheckLBConfigCommand due to ", e);
+ if (shouldRetry(numRetries)) {
+ return retry(cmd, numRetries);
+ } else {
+ return new HealthCheckLBConfigAnswer(hcLB);
+ }
+ } catch (Exception e) {
+ s_logger.error("Failed to execute HealthCheckLBConfigCommand due to ", e);
+ if (shouldRetry(numRetries)) {
+ return retry(cmd, numRetries);
+ } else {
+ return new HealthCheckLBConfigAnswer(hcLB);
+ }
+ }
+ return new HealthCheckLBConfigAnswer(hcLB);
+ }
+
+ private String getLBHealthChecks(long networkid) throws ExecutionException {
+ URI agentUri = null;
+ String response = null;
+ try {
+ agentUri =
+ new URI("https", null, _ip, DEFAULT_PORT,
+ "/cs/adcaas/v1/networks/"+ networkid +"/lbhealthstatus", null, null);
+ org.json.JSONObject jsonBody = new JSONObject();
+ response = getHttpRequest(jsonBody.toString(), agentUri, _sessionid);
+ s_logger.debug("LBHealthcheck Response :" + response);
+ } catch (URISyntaxException e) {
+ e.printStackTrace();
+ }
+ return response;
+ }
+ private synchronized Answer execute(LoadBalancerConfigCommand cmd, int numRetries) {
+ try {
+ LoadBalancerTO[] loadBalancers = cmd.getLoadBalancers();
+ if (loadBalancers == null) {
+ return new Answer(cmd);
+ }
+ JSONObject lbConfigPaylod = new JSONObject(cmd);
+ String gsonLBConfig = _gson.toJson(cmd);
+ URI agentUri = null;
+ agentUri =
+ new URI("https", null, _ip, DEFAULT_PORT,
+ "/cs/adcaas/v1/loadbalancerCmds", null, null);
+ JSONObject lbConfigCmd = new JSONObject();
+ JSONObject lbcmd = new JSONObject(gsonLBConfig);
+ s_logger.debug("LB config from gsonstring to JSONObject : " + lbcmd.toString() + "\n" + "gson cmd is :: \t" + gsonLBConfig);
+ lbConfigCmd.put("LoadBalancerConfigCommand", lbcmd.getJSONArray("loadBalancers"));
+ s_logger.debug("LB config paylod : " + lbConfigCmd.toString());
+
+ String result = postHttpRequest(lbConfigCmd.toString(), agentUri, _sessionid);
+ s_logger.debug("Result of lbconfigcmg is "+ result);
+ result = queryAsyncJob(result);
+ s_logger.debug("Done query async of LB ConfigCmd implement request and result:: " + result);
+ return new Answer(cmd);
+ } catch (ExecutionException e) {
+ s_logger.error("Failed to execute LoadBalancerConfigCommand due to ", e);
+ if(e.getMessage().equalsIgnoreCase(NccHttpCode.NOT_FOUND)) {
+ return new Answer(cmd, true, "LB Rule is not present in NS device. So returning as removed the LB Rule");
+ } else if(e.getMessage().startsWith("ERROR, ROLLBACK COMPLETED") || e.getMessage().startsWith("ERROR, ROLLBACK FAILED")) {
+ s_logger.error("Failed to execute LoadBalancerConfigCommand due to : " + e.getMessage());
+ return new Answer(cmd, false, e.getMessage());
+ } else if (e.getMessage().startsWith(NccHttpCode.INTERNAL_ERROR)) {
+ s_logger.error("Failed to execute LoadBalancerConfigCommand as Internal Error returning Internal error ::" + e.getMessage() );
+ return new Answer(cmd, false, e.getMessage());
+ }
+ if (shouldRetry(numRetries)) {
+ return retry(cmd, numRetries);
+ } else {
+ return new Answer(cmd, false, e.getMessage());
+ }
+ } catch (Exception e) {
+ s_logger.error("Failed to execute LoadBalancerConfigCommand due to ", e);
+ if (shouldRetry(numRetries)) {
+ return retry(cmd, numRetries);
+ } else {
+ return new Answer(cmd, false, e.getMessage());
+ }
+ }
+ }
+
+ private synchronized Answer execute(SetStaticNatRulesCommand cmd, int numRetries) {
+ return Answer.createUnsupportedCommandAnswer(cmd);
+ }
+
+ private synchronized Answer execute(ExternalNetworkResourceUsageCommand cmd, int numRetries) {
+ try {
+
+ return getPublicIpBytesSentAndReceived(cmd);
+
+ } catch (ExecutionException e) {
+ if (shouldRetry(numRetries)) {
+ return retry(cmd, numRetries);
+ } else {
+ return new ExternalNetworkResourceUsageAnswer(cmd, e);
+ }
+ }
+ }
+
+
+ private String getNetScalerProtocol(LoadBalancerTO loadBalancer) throws ExecutionException {
+ String port = Integer.toString(loadBalancer.getSrcPort());
+ String lbProtocol = loadBalancer.getLbProtocol();
+ StickinessPolicyTO[] stickyPolicies = loadBalancer.getStickinessPolicies();
+ String nsProtocol = "TCP";
+
+ if (lbProtocol == null)
+ lbProtocol = loadBalancer.getProtocol();
+
+ if ((stickyPolicies != null) && (stickyPolicies.length > 0) && (stickyPolicies[0] != null)) {
+ StickinessPolicyTO stickinessPolicy = stickyPolicies[0];
+ if (StickinessMethodType.LBCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName()) ||
+ (StickinessMethodType.AppCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName()))) {
+ nsProtocol = "HTTP";
+ return nsProtocol;
+ }
+ }
+
+ if (lbProtocol.equalsIgnoreCase(NetUtils.SSL_PROTO) || lbProtocol.equalsIgnoreCase(NetUtils.HTTP_PROTO))
+ return lbProtocol.toUpperCase();
+
+ if (port.equals(NetUtils.HTTP_PORT)) {
+ nsProtocol = "HTTP";
+ } else if (NetUtils.TCP_PROTO.equalsIgnoreCase(lbProtocol)) {
+ nsProtocol = "TCP";
+ } else if (NetUtils.UDP_PROTO.equalsIgnoreCase(lbProtocol)) {
+ nsProtocol = "UDP";
+ }
+
+ return nsProtocol;
+ }
+
+
+ private ExternalNetworkResourceUsageAnswer getPublicIpBytesSentAndReceived(ExternalNetworkResourceUsageCommand cmd) throws ExecutionException {
+ ExternalNetworkResourceUsageAnswer answer = new ExternalNetworkResourceUsageAnswer(cmd);
+ long networkid = cmd.getNetworkid();
+ try {
+ //TODO send GET cmd to get the network stats
+
+ URI agentUri = null;
+ String response = null;
+ try {
+ agentUri =
+ new URI("https", null, _ip, DEFAULT_PORT,
+ "/cs/adcaas/v1/networks/"+ networkid +"/ipStats", null, null);
+ org.json.JSONObject jsonBody = new JSONObject();
+ response = getHttpRequest(jsonBody.toString(), agentUri, _sessionid);
+ JSONArray statsIPList = null;
+ if(response !=null ) {
+ statsIPList = new JSONObject(response).getJSONObject("stats") .getJSONArray("ipBytes");
+ }
+ if(statsIPList != null) {
+ for(int i=0; i<statsIPList.length(); i++) {
+ JSONObject ipstat = statsIPList.getJSONObject(i);
+ JSONObject ipvalues = ipstat.getJSONObject("ipstats");
+ if(ipstat != null) {
+ long[] bytesSentAndReceived = new long[] {0, 0};
+ bytesSentAndReceived[0] = ipvalues.getLong("received");
+ bytesSentAndReceived[1] = ipvalues.getLong("sent");
+
+ if (bytesSentAndReceived[0] >= 0 && bytesSentAndReceived[1] >= 0) {
+ answer.ipBytes.put(ipstat.getString("ip"), bytesSentAndReceived);
+ }
+ }
+ }
+ }
+ s_logger.debug("IPStats Response :" + response);
+ } catch (URISyntaxException e) {
+ e.printStackTrace();
+ } catch (ExecutionException e) {
+ s_logger.debug("Seesion Alive" + e.getMessage());
+ e.printStackTrace();
+ }
+
+ } catch (Exception e) {
+ s_logger.error("Failed to get bytes sent and recived statistics due to " + e);
+ throw new ExecutionException(e.getMessage());
+ }
+
+ return answer;
+ }
+
+ private Answer retry(Command cmd, int numRetries) {
+ int numRetriesRemaining = numRetries - 1;
+ s_logger.warn("Retrying " + cmd.getClass().getSimpleName() + ". Number of retries remaining: " + numRetriesRemaining);
+ return executeRequest(cmd, numRetriesRemaining);
+ }
+
+ private boolean shouldRetry(int numRetries) {
+ try {
+ if (numRetries > 0) {
+ login();
+ return true;
+ }
+ } catch (Exception e) {
+ s_logger.error("Failed to log in to Netscaler ControlCenter device at " + _ip + " due to " + e.getMessage());
+ return false;
+ }
+ return false;
+ }
+
+
+ @Override
+ public IAgentControl getAgentControl() {
+ return null;
+ }
+
+ private boolean refreshNCCConnection() {
+ boolean ret = false;
+ try {
+ keepSessionAlive();
+ return true;
+ } catch (ExecutionException ex) {
+ s_logger.debug("Failed to keep up the session alive ", ex);
+ }
+ return ret;
+ }
+
+ @Override
+ public PingCommand getCurrentStatus(long id) {
+ pingCount++;
+ if (pingCount > 10 && refreshNCCConnection()) {
+ pingCount = 0;
+ }
+ return new PingCommand(Host.Type.NetScalerControlCenter, id);
+ }
+
+ @Override
+ public Type getType() {
+ return Host.Type.NetScalerControlCenter ;
+ }
+
+ @Override
+ public void setAgentControl(IAgentControl agentControl) {
+ return;
+ }
+
+ @Override
+ public String getName() {
+ return _name;
+ }
+
+ @Override
+ public void setName(String name) {
+ }
+
+ @Override
+ public boolean start() {
+ return true;
+ }
+
+ @Override
+ public boolean stop() {
+ return true;
+ }
+
+ @Override
+ public void disconnected() {
+ return;
+ }
+
+ @Override
+ public void setConfigParams(Map<String, Object> params) {
+ }
+
+ @Override
+ public Map<String, Object> getConfigParams() {
+ return null;
+ }
+
+ @Override
+ public int getRunLevel() {
+ return 0;
+ }
+
+ @Override
+ public void setRunLevel(int level) {
+ }
+
+ public String getSessionID() {
+ return _sessionid;
+ }
+ public static String cleanPassword(String logString) {
+ String cleanLogString = null;
+ if (logString != null) {
+ cleanLogString = logString;
+ String[] temp = logString.split(",");
+ int i = 0;
+ if (temp != null) {
+ while (i < temp.length) {
+ temp[i] = StringUtils.cleanString(temp[i]);
+ i++;
+ }
+ List<String> stringList = new ArrayList<String>();
+ Collections.addAll(stringList, temp);
+ cleanLogString = StringUtils.join(stringList, ",");
+ }
+ }
+ return cleanLogString;
+ }
+ public static HttpClient getHttpClient() {
+
+ HttpClient httpClient = null;
+ TrustStrategy easyStrategy = new TrustStrategy() {
+ @Override
+ public boolean isTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException {
+ return true;
+ }
+ };
+
+ try {
+ SSLSocketFactory sf = new SSLSocketFactory(easyStrategy, new AllowAllHostnameVerifier());
+ SchemeRegistry registry = new SchemeRegistry();
+ registry.register(new Scheme("https", DEFAULT_PORT, sf));
+ ClientConnectionManager ccm = new BasicClientConnectionManager(registry);
+ httpClient = new DefaultHttpClient(ccm);
+ } catch (KeyManagementException e) {
+ s_logger.error("failed to initialize http client " + e.getMessage());
+ } catch (UnrecoverableKeyException e) {
+ s_logger.error("failed to initialize http client " + e.getMessage());
+ } catch (NoSuchAlgorithmException e) {
+ s_logger.error("failed to initialize http client " + e.getMessage());
+ } catch (KeyStoreException e) {
+ s_logger.error("failed to initialize http client " + e.getMessage());
+ }
+ return httpClient;
+ }
+
+ public static String getHttpRequest(final String jsonCmd, final URI agentUri, String sessionID) throws ExecutionException {
+ // Using Apache's HttpClient for HTTP POST
+ // Java-only approach discussed at on StackOverflow concludes with
+ // comment to use Apache HttpClient
+ // http://stackoverflow.com/a/2793153/939250, but final comment is to
+ // use Apache.
+ String logMessage = StringEscapeUtils.unescapeJava(jsonCmd);
+ logMessage = cleanPassword(logMessage);
+ s_logger.debug("POST request to " + agentUri.toString()
+ + " with contents " + logMessage);
+
+ // Create request
+ HttpClient httpClient = getHttpClient();
+ String result = null;
+
+ // TODO: are there timeout settings and worker thread settings to tweak?
+ try {
+ HttpGet request = new HttpGet(agentUri);
+
+ // JSON encode command
+ // Assumes command sits comfortably in a string, i.e. not used for
+ // large data transfers
+ StringEntity cmdJson = new StringEntity(jsonCmd);
+ request.addHeader("content-type", "application/json");
+ request.addHeader("Cookie", "SessId=" + sessionID);
+ s_logger.debug("Sending cmd to " + agentUri.toString()
+ + " cmd data:" + logMessage);
+ HttpResponse response = httpClient.execute(request);
+
+ // Unsupported commands will not route.
+ if (response.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_FOUND) {
+ String errMsg = "Failed to send : HTTP error code : " + response.getStatusLine().getStatusCode();
+ s_logger.error(errMsg);
+ String unsupportMsg = "Unsupported command " + agentUri.getPath() + ". Are you sure you got the right f of" + " server?";
+ Answer ans = new UnsupportedAnswer(null, unsupportMsg);
+ s_logger.error(ans);
+ result = s_gson.toJson(new Answer[] {ans});
+ } else if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
+ String errMsg = "Failed send to " + agentUri.toString() + " : HTTP error code : " + response.getStatusLine().getStatusCode();
+ s_logger.error(errMsg);
+ throw new ExecutionException("UNAUTHORIZED");
+ } else {
+ result = EntityUtils.toString(response.getEntity());
+ String logResult = cleanPassword(StringEscapeUtils.unescapeJava(result));
+ s_logger.debug("Get response is " + logResult);
+ }
+ } catch (ClientProtocolException protocolEx) {
+ // Problem with HTTP message exchange
+ s_logger.error(protocolEx);
+ } catch (IOException connEx) {
+ // Problem with underlying communications
+ s_logger.error(connEx);
+ } finally {
+ httpClient.getConnectionManager().shutdown();
+ }
+ return result;
+ }
+
+ public static String postHttpRequest(final String jsonCmd, final URI agentUri, String sessionID) throws ExecutionException {
+ // Using Apache's HttpClient for HTTP POST
+ // Java-only approach discussed at on StackOverflow concludes with
+ // comment to use Apache HttpClient
+ // http://stackoverflow.com/a/2793153/939250, but final comment is to
+ // use Apache.
+ String logMessage = StringEscapeUtils.unescapeJava(jsonCmd);
+ logMessage = cleanPassword(logMessage);
+ s_logger.debug("POST request to " + agentUri.toString()
+ + " with contents " + logMessage);
+
+ // Create request
+ HttpClient httpClient = getHttpClient();
+ TrustStrategy easyStrategy = new TrustStrategy() {
+ @Override
+ public boolean isTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException {
+ return true;
+ }
+ };
+
+ try {
+ SSLSocketFactory sf = new SSLSocketFactory(easyStrategy, new AllowAllHostnameVerifier());
+ SchemeRegistry registry = new SchemeRegistry();
+ registry.register(new Scheme("https", DEFAULT_PORT, sf));
+ ClientConnectionManager ccm = new BasicClientConnectionManager(registry);
+ httpClient = new DefaultHttpClient(ccm);
+ } catch (KeyManagementException e) {
+ s_logger.error("failed to initialize http client " + e.getMessage());
+ } catch (UnrecoverableKeyException e) {
+ s_logger.error("failed to initialize http client " + e.getMessage());
+ } catch (NoSuchAlgorithmException e) {
+ s_logger.error("failed to initialize http client " + e.getMessage());
+ } catch (KeyStoreException e) {
+ s_logger.error("failed to initialize http client " + e.getMessage());
+ }
+
+ String result = null;
+
+ // TODO: are there timeout settings and worker thread settings to tweak?
+ try {
+ HttpPost request = new HttpPost(agentUri);
+
+ // JSON encode command
+ // Assumes command sits comfortably in a string, i.e. not used for
+ // large data transfers
+ StringEntity cmdJson = new StringEntity(jsonCmd);
+ request.addHeader("content-type", "application/json");
+ request.addHeader("Cookie", "SessId=" + sessionID);
+ request.setEntity(cmdJson);
+ s_logger.debug("Sending cmd to " + agentUri.toString()
+ + " cmd data:" + logMessage + "SEssion id: " + sessionID);
+ HttpResponse response = httpClient.execute(request);
+
+ // Unsupported commands will not route.
+ if (response.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_FOUND) {
+ String errMsg = "Failed : HTTP error code : " + response.getStatusLine().getStatusCode();
+ throw new ExecutionException(NccHttpCode.NOT_FOUND);
+ } else if ((response.getStatusLine().getStatusCode() != HttpStatus.SC_OK ) && (response.getStatusLine().getStatusCode() != HttpStatus.SC_CREATED )) {
+ String errMsg = "Command Not Success " + agentUri.toString() + " : HTTP error code : " + response.getStatusLine().getStatusCode();
+ s_logger.error(errMsg);
+ throw new ExecutionException(NccHttpCode.INTERNAL_ERROR + " " + errMsg);
+ } else if (response.getStatusLine().getStatusCode() == HttpStatus.SC_UNAUTHORIZED) {
+ //Successfully created the resource in the NCC, Now get the Job ID and send to the response
+ // make login request and store new session id
+ throw new ExecutionException(NccHttpCode.UNAUTHORIZED);
+ } else if (response.getStatusLine().getStatusCode() == HttpStatus.SC_CREATED) {
+ //Successfully created the resource in the NCC, Now get the Job ID and send to the response
+ result = response.getFirstHeader(NccHttpCode.JOB_ID).getValue();
+ } else {
+ result = EntityUtils.toString(response.getEntity());
+ String logResult = cleanPassword(StringEscapeUtils.unescapeJava(result));
+ s_logger.debug("POST response is " + logResult);
+ }
+
+ } catch (ClientProtocolException protocolEx) {
+ // Problem with HTTP message exchange
+ s_logger.error(protocolEx);
+ } catch (IOException connEx) {
+ // Problem with underlying communications
+ s_logger.error(connEx);
+ } finally {
+ httpClient.getConnectionManager().shutdown();
+ }
+ return result;
+ }
+}
diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/vm/NetScalerVMManager.java b/plugins/network-elements/netscaler/src/com/cloud/network/vm/NetScalerVMManager.java
new file mode 100644
index 00000000000..c82d2b8e0f5
--- /dev/null
+++ b/plugins/network-elements/netscaler/src/com/cloud/network/vm/NetScalerVMManager.java
@@ -0,0 +1,42 @@
+//Licensed to the Apache Software Foundation (ASF) under one
+//or more contributor license agreements. See the NOTICE file
+//distributed with this work for additional information
+//regarding copyright ownership. The ASF licenses this file
+//to you under the Apache License, Version 2.0 (the
+//"License"); you may not use this file except in compliance
+//with the License. You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing,
+//software distributed under the License is distributed on an
+//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+//KIND, either express or implied. See the License for the
+//specific language governing permissions and limitations
+//under the License.
+
+package com.cloud.network.vm;
+import java.util.Map;
+
+import com.cloud.api.commands.DeployNetscalerVpxCmd;
+import com.cloud.deploy.DeployDestination;
+import com.cloud.deploy.DeploymentPlan;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.router.VirtualRouter;
+import com.cloud.user.Account;
+
+public interface NetScalerVMManager {
+ //RAM/CPU for the system offering used by Internal LB VMs
+ int DEFAULT_NETSCALER_VM_RAMSIZE = 2048; // 2048 MB
+ int DEFAULT_NETSCALER_VM_CPU_MHZ = 1024; // 1024 MHz
+
+ Map<String, Object> deployNetscalerServiceVm(DeployNetscalerVpxCmd cmd);
+
+ VirtualRouter stopNetscalerServiceVm(Long id, boolean forced, Account callingAccount, long callingUserId) throws ConcurrentOperationException, ResourceUnavailableException;
+
+ Map<String, Object> deployNsVpx(Account owner, DeployDestination dest, DeploymentPlan plan, long svcOffId, long templateId) throws InsufficientCapacityException;
+
+ VirtualRouter stopNetScalerVm(Long id, boolean forced, Account callingAccount, long callingUserId);
+}
\ No newline at end of file
diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/vm/NetScalerVMManagerImpl.java b/plugins/network-elements/netscaler/src/com/cloud/network/vm/NetScalerVMManagerImpl.java
new file mode 100644
index 00000000000..8d50b59c0fd
--- /dev/null
+++ b/plugins/network-elements/netscaler/src/com/cloud/network/vm/NetScalerVMManagerImpl.java
@@ -0,0 +1,448 @@
+//Licensed to the Apache Software Foundation (ASF) under one
+//or more contributor license agreements. See the NOTICE file
+//distributed with this work for additional information
+//regarding copyright ownership. The ASF licenses this file
+//to you under the Apache License, Version 2.0 (the
+//"License"); you may not use this file except in compliance
+//with the License. You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing,
+//software distributed under the License is distributed on an
+//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+//KIND, either express or implied. See the License for the
+//specific language governing permissions and limitations
+//under the License.
+package com.cloud.network.vm;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.manager.Commands;
+import com.cloud.api.commands.DeployNetscalerVpxCmd;
+import com.cloud.dc.DataCenter;
+import com.cloud.dc.DataCenter.NetworkType;
+import com.cloud.dc.DataCenterVO;
+import com.cloud.dc.VlanVO;
+import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.dc.dao.VlanDao;
+import com.cloud.deploy.DataCenterDeployment;
+import com.cloud.deploy.DeployDestination;
+import com.cloud.deploy.DeploymentPlan;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.OperationTimedoutException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.exception.StorageUnavailableException;
+import com.cloud.network.IpAddressManager;
+import com.cloud.network.Network;
+import com.cloud.network.Network.Provider;
+import com.cloud.network.NetworkModel;
+import com.cloud.network.Networks.TrafficType;
+import com.cloud.network.PhysicalNetwork;
+import com.cloud.network.PhysicalNetworkServiceProvider;
+import com.cloud.network.VirtualRouterProvider;
+import com.cloud.network.dao.NetworkDao;
+import com.cloud.network.dao.NetworkVO;
+import com.cloud.network.dao.PhysicalNetworkDao;
+import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
+import com.cloud.network.dao.VirtualRouterProviderDao;
+import com.cloud.network.element.VirtualRouterProviderVO;
+import com.cloud.network.lb.LoadBalancingRulesManager;
+import com.cloud.network.router.VirtualRouter;
+import com.cloud.network.router.VirtualRouter.RedundantState;
+import com.cloud.network.router.VirtualRouter.Role;
+import com.cloud.offering.NetworkOffering;
+import com.cloud.offerings.dao.NetworkOfferingDao;
+import com.cloud.resource.ResourceManager;
+import com.cloud.service.ServiceOfferingVO;
+import com.cloud.service.dao.ServiceOfferingDao;
+import com.cloud.storage.VMTemplateVO;
+import com.cloud.storage.dao.VMTemplateDao;
+import com.cloud.user.Account;
+import com.cloud.user.AccountManager;
+import com.cloud.utils.component.ManagerBase;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.DomainRouterVO;
+import com.cloud.vm.NicProfile;
+import com.cloud.vm.ReservationContext;
+import com.cloud.vm.VMInstanceVO;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachineGuru;
+import com.cloud.vm.VirtualMachineManager;
+import com.cloud.vm.VirtualMachineName;
+import com.cloud.vm.VirtualMachineProfile;
+import com.cloud.vm.VirtualMachineProfile.Param;
+import com.cloud.vm.dao.DomainRouterDao;
+import com.cloud.vm.dao.NicDao;
+import com.cloud.vm.dao.VMInstanceDao;
+
+@Local(value = {NetScalerVMManager.class})
+public class NetScalerVMManagerImpl extends ManagerBase implements NetScalerVMManager, VirtualMachineGuru {
+ private static final Logger s_logger = Logger.getLogger(NetScalerVMManagerImpl.class);
+ static final private String NetScalerLbVmNamePrefix = "NS";
+
+ @Inject
+ IpAddressManager _ipAddrMgr;
+ @Inject
+ VirtualMachineManager _itMgr;
+ @Inject
+ DomainRouterDao _internalLbVmDao;
+ @Inject
+ ConfigurationDao _configDao;
+ @Inject
+ AgentManager _agentMgr;
+ @Inject
+ DataCenterDao _dcDao;
+ @Inject
+ VirtualRouterProviderDao _vrProviderDao;
+ @Inject
+ ApplicationLoadBalancerRuleDao _lbDao;
+ @Inject
+ NetworkModel _ntwkModel;
+ @Inject
+ LoadBalancingRulesManager _lbMgr;
+ @Inject
+ NicDao _nicDao;
+ @Inject
+ AccountManager _accountMgr;
+ @Inject
+ NetworkDao _networkDao;
+ @Inject
+ NetworkOrchestrationService _networkMgr;
+ @Inject
+ ServiceOfferingDao _serviceOfferingDao;
+ @Inject
+ PhysicalNetworkServiceProviderDao _physicalProviderDao;
+ @Inject
+ NetworkOfferingDao _networkOfferingDao;
+ @Inject
+ VMTemplateDao _templateDao;
+ @Inject
+ ResourceManager _resourceMgr;
+ @Inject
+ VMInstanceDao _vmDao;
+ @Inject
+ NetworkModel _networkModel;
+ @Inject
+ PhysicalNetworkDao _physicalNetworkDao;
+ @Inject
+ VlanDao _vlanDao;
+ @Inject
+ DomainRouterDao _routerDao;
+
+ @Override
+ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) {
+ //NetScalerLB vm starts up with 3 Nics
+ //Nic #1 - NS IP
+ //Nic #2 - locallink(guest network)
+ //Nic #3 - public nic
+
+ for (final NicProfile nic : profile.getNics()) {
+ if(nic.getTrafficType() == TrafficType.Control) {
+ nic.setTrafficType(TrafficType.Guest);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException {
+ return true;
+ }
+
+ @Override
+ public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) {
+ return true;
+ }
+
+ @Override
+ public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile profile) {
+ return true;
+ }
+
+ @Override
+ public void finalizeStop(VirtualMachineProfile profile, Answer answer) {
+ }
+
+ @Override
+ public void finalizeExpunge(VirtualMachine vm) {
+ }
+
+ @Override
+ public void prepareStop(VirtualMachineProfile profile) {
+ }
+
+ @Override
+ public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+ _itMgr.registerGuru(VirtualMachine.Type.NetScalerVm, this);
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info(getName() + " has been configured");
+ }
+ return true;
+ }
+
+ @Override
+ public String getName() {
+ return _name;
+ }
+
+ protected VirtualRouter stopInternalLbVm(DomainRouterVO internalLbVm, boolean forced, Account caller, long callerUserId) throws ResourceUnavailableException, ConcurrentOperationException {
+ s_logger.debug("Stopping internal lb vm " + internalLbVm);
+ try {
+ _itMgr.advanceStop(internalLbVm.getUuid(), forced);
+ return _internalLbVmDao.findById(internalLbVm.getId());
+ } catch (OperationTimedoutException e) {
+ throw new CloudRuntimeException("Unable to stop " + internalLbVm, e);
+ }
+ }
+
+ public VirtualRouterProvider addNetScalerLoadBalancerElement(long ntwkSvcProviderId) {
+ VirtualRouterProviderVO element = _vrProviderDao.findByNspIdAndType(ntwkSvcProviderId, com.cloud.network.VirtualRouterProvider.Type.NetScalerVm);
+ if (element != null) {
+ s_logger.debug("There is already an " + getName() + " with service provider id " + ntwkSvcProviderId);
+ return element;
+ }
+
+ PhysicalNetworkServiceProvider provider = _physicalProviderDao.findById(ntwkSvcProviderId);
+ if (provider == null || !provider.getProviderName().equalsIgnoreCase(getName())) {
+ throw new InvalidParameterValueException("Invalid network service provider is specified");
+ }
+
+ element = new VirtualRouterProviderVO(ntwkSvcProviderId, com.cloud.network.VirtualRouterProvider.Type.NetScalerVm);
+ element.setEnabled(true);
+ element = _vrProviderDao.persist(element);
+ return element;
+ }
+
+ protected long getNetScalerLbProviderId(long physicalNetworkId) {
+ //final long physicalNetworkId = _ntwkModel.getPhysicalNetworkId(guestNetwork);
+
+ final PhysicalNetworkServiceProvider provider = _physicalProviderDao.findByServiceProvider(physicalNetworkId, "Netscaler");
+ if (provider == null) {
+ throw new CloudRuntimeException("Cannot find service provider " + Provider.Netscaler.toString() + " in physical network " + physicalNetworkId);
+ }
+
+ //TODO: get from type
+ VirtualRouterProvider netScalerLbProvider = _vrProviderDao.findByNspIdAndType(provider.getId(), com.cloud.network.VirtualRouterProvider.Type.NetScalerVm);
+ if (netScalerLbProvider == null) {
+ //create the vrp for netscalerVM.
+ netScalerLbProvider = addNetScalerLoadBalancerElement(provider.getId());
+ }
+
+ return netScalerLbProvider.getId();
+ }
+
+ @Override
+ public Map<String, Object> deployNsVpx(Account owner, DeployDestination dest, DeploymentPlan plan, long svcOffId, long templateId) throws InsufficientCapacityException {
+
+ VMTemplateVO template = _templateDao.findById(templateId) ;
+ long id = _vmDao.getNextInSequence(Long.class, "id");
+ Account systemAcct = _accountMgr.getSystemAccount();
+
+ if (template == null) {
+ s_logger.error(" Unable to find the NS VPX template");
+ throw new CloudRuntimeException("Unable to find the Template" + templateId);
+ }
+ long dataCenterId = dest.getDataCenter().getId();
+ DataCenterVO dc = _dcDao.findById(dest.getDataCenter().getId());
+
+ String nxVpxName = VirtualMachineName.getSystemVmName(id, "Vpx", NetScalerLbVmNamePrefix);
+
+ ServiceOfferingVO vpxOffering = _serviceOfferingDao.findById(svcOffId); //using 2GB and 2CPU offering
+ if(vpxOffering.getRamSize() < 2048 && vpxOffering.getCpu() <2 ) {
+ throw new InvalidParameterValueException("Specified Service Offering :" + vpxOffering.getUuid() + " NS Vpx cannot be deployed. Min 2GB Ram and 2 CPU are required");
+ }
+
+ long userId = CallContext.current().getCallingUserId();
+ //TODO change the os bits from 142 103 to the actual guest of bits
+ if(template.getGuestOSId() != 103 ) {
+ throw new InvalidParameterValueException("Specified Template " + template.getUuid()+ " not suitable for NS VPX Deployment. Please register the template with guest os type as unknow(64-bit)");
+ }
+
+ NetworkVO defaultNetwork = null;
+ NetworkVO defaultPublicNetwork = null;
+ if (dc.getNetworkType() == NetworkType.Advanced && dc.isSecurityGroupEnabled()) {
+ List<NetworkVO> networks = _networkDao.listByZoneSecurityGroup(dataCenterId);
+ if (networks == null || networks.size() == 0) {
+ throw new CloudRuntimeException("Can not found security enabled network in SG Zone " + dc);
+ }
+ defaultNetwork = networks.get(0);
+ } else {
+ TrafficType defaultTrafficType = TrafficType.Management;
+ List<NetworkVO> defaultNetworks = _networkDao.listByZoneAndTrafficType(dataCenterId, defaultTrafficType);
+
+ TrafficType publicTrafficType = TrafficType.Public;
+ List<NetworkVO> publicNetworks = _networkDao.listByZoneAndTrafficType(dataCenterId, publicTrafficType);
+
+ // api should never allow this situation to happen
+ if (defaultNetworks.size() != 1) {
+ throw new CloudRuntimeException("Found " + defaultNetworks.size() + " networks of type " + defaultTrafficType + " when expect to find 1");
+ }
+
+ if (publicNetworks.size() != 1) {
+ throw new CloudRuntimeException("Found " + defaultNetworks.size() + " networks of type " + defaultTrafficType + " when expect to find 1");
+ }
+ defaultPublicNetwork = publicNetworks.get(0);
+ defaultNetwork = defaultNetworks.get(0);
+ }
+
+ LinkedHashMap<Network, List<? extends NicProfile>> networks = new LinkedHashMap<Network, List<? extends NicProfile>>(4);
+ NicProfile defaultNic = new NicProfile();
+ defaultNic.setDefaultNic(true);
+ defaultNic.setDeviceId(0);
+
+ networks.put(_networkMgr.setupNetwork(_accountMgr.getSystemAccount() , _networkOfferingDao.findById(defaultNetwork.getNetworkOfferingId()), plan, null, null, false).get(0), new ArrayList<NicProfile>());
+
+ NicProfile defaultNic1 = new NicProfile();
+ defaultNic1.setDefaultNic(false);
+ defaultNic1.setDeviceId(1);
+
+ NicProfile defaultNic2 = new NicProfile();
+ defaultNic2.setDefaultNic(false);
+ defaultNic2.setDeviceId(2);
+ defaultNic2.setIPv4Address("");
+ defaultNic2.setIPv4Gateway("");
+ defaultNic2.setIPv4Netmask("");
+ String macAddress = _networkDao.getNextAvailableMacAddress(defaultPublicNetwork.getId(), null);
+ defaultNic2.setMacAddress(macAddress);
+
+ networks.put(_networkMgr.setupNetwork(_accountMgr.getSystemAccount(), _networkOfferingDao.findByUniqueName(NetworkOffering.SystemPublicNetwork), plan, null, null, false).get(0),
+ new ArrayList<NicProfile>(Arrays.asList(defaultNic2)));
+
+ networks.put(_networkMgr.setupNetwork(_accountMgr.getSystemAccount(), _networkOfferingDao.findByUniqueName(NetworkOffering.SystemControlNetwork), plan, null, null, false).get(0),
+ new ArrayList<NicProfile>());
+
+ long physicalNetworkId = _networkModel.findPhysicalNetworkId(dataCenterId, _networkOfferingDao.findById(defaultPublicNetwork.getNetworkOfferingId()).getTags(), TrafficType.Public);
+ // Validate physical network
+ PhysicalNetwork physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId);
+ if (physicalNetwork == null) {
+ throw new InvalidParameterValueException("Unable to find physical network with id: " + physicalNetworkId + " and tag: "
+ + _networkOfferingDao.findById(defaultPublicNetwork.getNetworkOfferingId()).getTags());
+ }
+ String guestvnet = physicalNetwork.getVnetString();
+
+ final List<VlanVO> vlans = _vlanDao.listByZone(dataCenterId);
+ List<String> pvlan = new ArrayList<String>();
+ for (final VlanVO vlan : vlans) {
+ pvlan.add(vlan.getVlanTag());
+ }
+
+ long netScalerProvider = getNetScalerLbProviderId(physicalNetworkId);
+ DomainRouterVO nsVpx = new DomainRouterVO(id, vpxOffering.getId(), netScalerProvider, nxVpxName,
+ template.getId(), template.getHypervisorType(), template.getGuestOSId(), owner.getDomainId(), owner.getId(), userId, false, RedundantState.UNKNOWN, false,
+ false, VirtualMachine.Type.NetScalerVm, null);
+
+ nsVpx.setRole(Role.NETSCALER_VM);
+
+ nsVpx = _routerDao.persist(nsVpx);
+
+ VMInstanceVO vmVO= _vmDao.findVMByHostName(nxVpxName);
+ _itMgr.allocate(nxVpxName, template, vpxOffering, networks, plan, template.getHypervisorType());
+ Map<Param, Object> params = new HashMap<VirtualMachineProfile.Param, Object>(1);
+ try {
+ if (vmVO != null) {
+ startNsVpx(vmVO, params);
+ } else {
+ throw new NullPointerException();
+ }
+ } catch (StorageUnavailableException e) {
+ e.printStackTrace();
+ } catch (ConcurrentOperationException e) {
+ e.printStackTrace();
+ } catch (ResourceUnavailableException e) {
+ e.printStackTrace();
+ }
+ vmVO= _vmDao.findByUuid(nsVpx.getUuid());
+ Map<String, Object> deployResponse = new HashMap<String, Object>();
+ deployResponse.put("vm", vmVO);
+ deployResponse.put("guestvlan", guestvnet);
+ deployResponse.put("publicvlan", pvlan);
+
+ return deployResponse;
+ }
+
+ protected void startNsVpx(VMInstanceVO nsVpx, Map<Param, Object> params) throws StorageUnavailableException,
+ InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException {
+ s_logger.debug("Starting NS Vpx " + nsVpx);
+ _itMgr.start(nsVpx.getUuid(), params, null, null);
+ }
+
+ @Override
+ public Map<String,Object> deployNetscalerServiceVm(DeployNetscalerVpxCmd cmd) {
+ DataCenter zone = _dcDao.findById(cmd.getZoneId());
+ DeployDestination dest = new DeployDestination(zone, null, null, null);
+ VMInstanceVO vmvo = null;
+ Map<String,Object> resp = new HashMap<String, Object>();
+ Long templateId = cmd.getTemplateId();
+ Long serviceOfferingId = cmd.getServiceOfferingId();
+ DeploymentPlan plan = new DataCenterDeployment(dest.getDataCenter().getId());
+
+ try {
+ resp = deployNsVpx(cmd.getAccount(), dest, plan, serviceOfferingId, templateId);
+ } catch (InsufficientCapacityException e) {
+ e.printStackTrace();
+ }
+
+ return resp;
+ }
+
+ protected VirtualRouter stopNetScalerVm(final long vmId, final boolean forced, final Account caller, final long callerUserId) throws ResourceUnavailableException, ConcurrentOperationException {
+ final DomainRouterVO netscalerVm = _routerDao.findById(vmId);
+ s_logger.debug("Stopping NetScaler vm " + netscalerVm);
+
+ if (netscalerVm == null || netscalerVm.getRole() != Role.NETSCALER_VM) {
+ throw new InvalidParameterValueException("Can't find NetScaler vm by id specified");
+ }
+
+ _accountMgr.checkAccess(caller, null, true, netscalerVm);
+
+ try {
+ _itMgr.expunge(netscalerVm.getUuid());
+ return _routerDao.findById(netscalerVm.getId());
+ } catch (final Exception e) {
+ throw new CloudRuntimeException("Unable to stop " + netscalerVm, e);
+ }
+ }
+
+ @Override
+ public VirtualRouter stopNetscalerServiceVm(Long id, boolean forced, Account callingAccount, long callingUserId) throws ConcurrentOperationException, ResourceUnavailableException {
+ return stopNetScalerVm(id, forced, callingAccount, callingUserId);
+ }
+
+ @Override
+ public VirtualRouter stopNetScalerVm(Long vmId, boolean forced, Account caller, long callingUserId) {
+ final DomainRouterVO netscalerVm = _routerDao.findById(vmId);
+ s_logger.debug("Stopping NetScaler vm " + netscalerVm);
+
+ if (netscalerVm == null || netscalerVm.getRole() != Role.NETSCALER_VM) {
+ throw new InvalidParameterValueException("Can't find NetScaler vm by id specified");
+ }
+ _accountMgr.checkAccess(caller, null, true, netscalerVm);
+ try {
+ _itMgr.expunge(netscalerVm.getUuid());
+ return _routerDao.findById(netscalerVm.getId());
+ } catch (final Exception e) {
+ throw new CloudRuntimeException("Unable to stop " + netscalerVm, e);
+ }
+ }
+}
diff --git a/plugins/network-elements/nicira-nvp/pom.xml b/plugins/network-elements/nicira-nvp/pom.xml
index 15027dfd759..8f14779fdc9 100644
--- a/plugins/network-elements/nicira-nvp/pom.xml
+++ b/plugins/network-elements/nicira-nvp/pom.xml
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
@@ -34,7 +34,7 @@
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-utils</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
diff --git a/plugins/network-elements/nicira-nvp/src/main/java/com/cloud/network/guru/NiciraNvpGuestNetworkGuru.java b/plugins/network-elements/nicira-nvp/src/main/java/com/cloud/network/guru/NiciraNvpGuestNetworkGuru.java
index 551269cc84c..548884e492f 100644
--- a/plugins/network-elements/nicira-nvp/src/main/java/com/cloud/network/guru/NiciraNvpGuestNetworkGuru.java
+++ b/plugins/network-elements/nicira-nvp/src/main/java/com/cloud/network/guru/NiciraNvpGuestNetworkGuru.java
@@ -113,7 +113,7 @@
public NiciraNvpGuestNetworkGuru() {
super();
- _isolationMethods = new IsolationMethod[] { IsolationMethod.STT, IsolationMethod.VXLAN };
+ _isolationMethods = new IsolationMethod[] { new IsolationMethod("STT", "NiciraNvp"), new IsolationMethod("VXLAN","NiciraNvp") };
}
@Override
diff --git a/plugins/network-elements/nuage-vsp/pom.xml b/plugins/network-elements/nuage-vsp/pom.xml
index be15e530a36..fe51c8b0d51 100644
--- a/plugins/network-elements/nuage-vsp/pom.xml
+++ b/plugins/network-elements/nuage-vsp/pom.xml
@@ -25,7 +25,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<repositories>
@@ -35,7 +35,7 @@
</repository>
</repositories>
<properties>
- <nuage.vsp.client.version>1.0.1</nuage.vsp.client.version>
+ <nuage.vsp.client.version>1.0.5</nuage.vsp.client.version>
</properties>
<dependencies>
<dependency>
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/ImplementNetworkVspAnswer.java b/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/ImplementNetworkVspAnswer.java
new file mode 100644
index 00000000000..03ab183d7b5
--- /dev/null
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/ImplementNetworkVspAnswer.java
@@ -0,0 +1,45 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package com.cloud.agent.api.manager;
+
+import net.nuage.vsp.acs.client.api.model.NetworkRelatedVsdIds;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.guru.ImplementNetworkVspCommand;
+
+/**
+ * Created by sgoeminn on 3/24/17.
+ */
+public class ImplementNetworkVspAnswer extends Answer {
+ private NetworkRelatedVsdIds networkRelatedVsdIds;
+
+ public ImplementNetworkVspAnswer(ImplementNetworkVspCommand command, NetworkRelatedVsdIds networkRelatedVsdIds) {
+ super(command);
+ this.networkRelatedVsdIds = networkRelatedVsdIds;
+ }
+
+ public ImplementNetworkVspAnswer(ImplementNetworkVspCommand command, Exception e) {
+ super(command, e);
+ }
+
+ public NetworkRelatedVsdIds getNetworkRelatedVsdIds() {
+ return networkRelatedVsdIds;
+ }
+}
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/element/NuageVspElement.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/element/NuageVspElement.java
index f2c13054f28..a7ce8c8d403 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/network/element/NuageVspElement.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/element/NuageVspElement.java
@@ -29,8 +29,6 @@
import javax.inject.Inject;
import javax.naming.ConfigurationException;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
import net.nuage.vsp.acs.client.api.model.VspAclRule;
import net.nuage.vsp.acs.client.api.model.VspDhcpDomainOption;
import net.nuage.vsp.acs.client.api.model.VspNetwork;
@@ -40,8 +38,11 @@
import org.apache.log4j.Logger;
import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
+import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import org.apache.cloudstack.api.InternalIdentity;
@@ -81,7 +82,6 @@
import com.cloud.network.Network.Service;
import com.cloud.network.NetworkModel;
import com.cloud.network.Networks;
-import com.cloud.network.PhysicalNetwork;
import com.cloud.network.PhysicalNetworkServiceProvider;
import com.cloud.network.PublicIpAddress;
import com.cloud.network.dao.FirewallRulesCidrsDao;
@@ -522,9 +522,18 @@ public boolean applyStaticNats(Network config, List<? extends StaticNat> rules)
VlanVO sourceNatVlan = _vlanDao.findById(sourceNatIp.getVlanId());
checkVlanUnderlayCompatibility(sourceNatVlan);
+ if (!staticNat.isForRevoke()) {
+ final List<FirewallRuleVO> firewallRules = _firewallRulesDao.listByIpAndNotRevoked(staticNat.getSourceIpAddressId());
+ for (FirewallRuleVO firewallRule : firewallRules) {
+ _nuageVspEntityBuilder.buildVspAclRule(firewallRule, config, sourceNatIp);
+ }
+ }
+
NicVO nicVO = _nicDao.findByIp4AddressAndNetworkId(staticNat.getDestIpAddress(), staticNat.getNetworkId());
VspStaticNat vspStaticNat = _nuageVspEntityBuilder.buildVspStaticNat(staticNat.isForRevoke(), sourceNatIp, sourceNatVlan, nicVO);
vspStaticNatDetails.add(vspStaticNat);
+
+
}
VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(config);
@@ -633,7 +642,7 @@ public boolean applyNetworkACLs(Network config, List<? extends NetworkACLItem> r
@Override
public boolean implementVpc(Vpc vpc, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
List<VpcOfferingServiceMapVO> vpcOfferingServices = _vpcOfferingSrvcDao.listByVpcOffId(vpc.getVpcOfferingId());
- Map<Network.Service, Set<Network.Provider>> supportedVpcServices = NuageVspManagerImpl.NUAGE_VSP_VPC_SERVICE_MAP;
+ Multimap<Service, Provider> supportedVpcServices = NuageVspManagerImpl.NUAGE_VSP_VPC_SERVICE_MAP;
for (VpcOfferingServiceMapVO vpcOfferingService : vpcOfferingServices) {
Network.Service service = Network.Service.getService(vpcOfferingService.getService());
if (!supportedVpcServices.containsKey(service)) {
@@ -642,7 +651,7 @@ public boolean implementVpc(Vpc vpc, DeployDestination dest, ReservationContext
}
Network.Provider provider = Network.Provider.getProvider(vpcOfferingService.getProvider());
- if (!supportedVpcServices.get(service).contains(provider)) {
+ if (!supportedVpcServices.containsEntry(service, provider)) {
s_logger.warn(String.format("NuageVsp doesn't support provider %s for service %s for VPCs", provider.getName(), service.getName()));
return false;
}
@@ -694,7 +703,7 @@ private Long getPhysicalNetworkId(Long zoneId) {
Long guestPhysicalNetworkId = 0L;
List<PhysicalNetworkVO> physicalNetworkList = _physicalNetworkDao.listByZone(zoneId);
for (PhysicalNetworkVO phyNtwk : physicalNetworkList) {
- if (phyNtwk.getIsolationMethods().contains(PhysicalNetwork.IsolationMethod.VSP.name())) {
+ if (phyNtwk.getIsolationMethods().contains("VSP")) {
guestPhysicalNetworkId = phyNtwk.getId();
break;
}
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/guru/NuageVspGuestNetworkGuru.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/guru/NuageVspGuestNetworkGuru.java
index 735356a71df..0a4733be244 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/network/guru/NuageVspGuestNetworkGuru.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/guru/NuageVspGuestNetworkGuru.java
@@ -25,9 +25,25 @@
import javax.inject.Inject;
+import net.nuage.vsp.acs.client.api.model.NetworkRelatedVsdIds;
+import net.nuage.vsp.acs.client.api.model.VspDhcpDomainOption;
+import net.nuage.vsp.acs.client.api.model.VspDhcpVMOption;
+import net.nuage.vsp.acs.client.api.model.VspDomain;
+import net.nuage.vsp.acs.client.api.model.VspNetwork;
+import net.nuage.vsp.acs.client.api.model.VspNic;
+import net.nuage.vsp.acs.client.api.model.VspStaticNat;
+import net.nuage.vsp.acs.client.api.model.VspVm;
+
+import org.apache.log4j.Logger;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.LinkedListMultimap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
import org.apache.cloudstack.resourcedetail.VpcDetailVO;
import org.apache.cloudstack.resourcedetail.dao.VpcDetailsDao;
-import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
@@ -36,6 +52,7 @@
import com.cloud.agent.api.guru.ReserveVmInterfaceVspCommand;
import com.cloud.agent.api.guru.TrashNetworkVspCommand;
import com.cloud.agent.api.guru.UpdateDhcpOptionVspCommand;
+import com.cloud.agent.api.manager.ImplementNetworkVspAnswer;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenter.NetworkType;
@@ -82,20 +99,6 @@
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.VMInstanceDao;
-import com.google.common.base.Strings;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.LinkedListMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-import net.nuage.vsp.acs.client.api.model.VspDhcpDomainOption;
-import net.nuage.vsp.acs.client.api.model.VspDhcpVMOption;
-import net.nuage.vsp.acs.client.api.model.VspDomain;
-import net.nuage.vsp.acs.client.api.model.VspNetwork;
-import net.nuage.vsp.acs.client.api.model.VspNic;
-import net.nuage.vsp.acs.client.api.model.VspStaticNat;
-import net.nuage.vsp.acs.client.api.model.VspVm;
public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
public static final Logger s_logger = Logger.getLogger(NuageVspGuestNetworkGuru.class);
@@ -131,7 +134,7 @@
public NuageVspGuestNetworkGuru() {
super();
- _isolationMethods = new IsolationMethod[] {IsolationMethod.VSP};
+ _isolationMethods = new IsolationMethod[] {new IsolationMethod("VSP")};
}
@Override
@@ -154,6 +157,7 @@ public Network design(NetworkOffering offering, DeploymentPlan plan, Network use
return networkObject;
}
+ /** In case an externalId is specified, we get called here, and store the id the same way as cached data */
@Override
public Network implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapacityException {
long networkId = network.getId();
@@ -206,7 +210,7 @@ public Network implement(Network network, NetworkOffering offering, DeployDestin
implemented.setBroadcastUri(Networks.BroadcastDomainType.Vsp.toUri(broadcastUriStr));
implemented.setBroadcastDomainType(Networks.BroadcastDomainType.Vsp);
- if (!implement(physicalNetworkId, vspNetwork, _nuageVspEntityBuilder.buildNetworkDhcpOption(network, offering))) {
+ if (!implement(network.getVpcId(), physicalNetworkId, vspNetwork, _nuageVspEntityBuilder.buildNetworkDhcpOption(network, offering))) {
return null;
}
@@ -227,10 +231,10 @@ public Network implement(Network network, NetworkOffering offering, DeployDestin
return implemented;
}
- private boolean implement(long physicalNetworkId, VspNetwork vspNetwork, VspDhcpDomainOption vspDhcpDomainOption) {
+ private boolean implement(Long vpcId, long physicalNetworkId, VspNetwork vspNetwork, VspDhcpDomainOption vspDhcpDomainOption) {
HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(physicalNetworkId);
ImplementNetworkVspCommand cmd = new ImplementNetworkVspCommand(vspNetwork, vspDhcpDomainOption);
- Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd);
+ ImplementNetworkVspAnswer answer = (ImplementNetworkVspAnswer) _agentMgr.easySend(nuageVspHost.getId(), cmd);
if (answer == null || !answer.getResult()) {
s_logger.error("ImplementNetworkVspCommand for network " + vspNetwork.getUuid() + " failed on Nuage VSD " + nuageVspHost.getDetail("hostname"));
if ((null != answer) && (null != answer.getDetails())) {
@@ -238,9 +242,54 @@ private boolean implement(long physicalNetworkId, VspNetwork vspNetwork, VspDhcp
}
return false;
}
+ saveNetworkAndVpcDetails(vspNetwork, answer.getNetworkRelatedVsdIds(), vpcId);
return true;
}
+ private void saveNetworkAndVpcDetails(VspNetwork vspNetwork, NetworkRelatedVsdIds networkRelatedVsdIds, Long vpcId) {
+
+
+ if (!vspNetwork.isShared() && !vspNetwork.getNetworkRelatedVsdIds().equals(networkRelatedVsdIds)) {
+ Map<String, String> networkDetails = constructNetworkDetails(networkRelatedVsdIds, vspNetwork.isVpc());
+
+ for (Map.Entry<String, String> networkDetail : networkDetails.entrySet()) {
+ NetworkDetailVO networkDetailVO = new NetworkDetailVO(vspNetwork.getId(), networkDetail.getKey(), networkDetail.getValue(), false);
+ _networkDetailsDao.persist(networkDetailVO);
+ }
+
+ if(vspNetwork.isVpc()) {
+ Map<String, String> vpcDetails = constructVpcDetails(networkRelatedVsdIds);
+
+ for (Map.Entry<String, String> vpcDetail : vpcDetails.entrySet()) {
+ VpcDetailVO vpcDetailVO = new VpcDetailVO(vpcId, vpcDetail.getKey(), vpcDetail.getValue(), false);
+ _vpcDetailsDao.persist(vpcDetailVO);
+ }
+ }
+ }
+ }
+
+ private static Map<String, String> constructNetworkDetails(NetworkRelatedVsdIds networkRelatedVsdIds, boolean isVpc) {
+ Map<String, String> networkDetails = Maps.newHashMap();
+
+ if(!isVpc) {
+ networkRelatedVsdIds.getVsdDomainId().ifPresent(v -> networkDetails.put(NuageVspManager.NETWORK_METADATA_VSD_DOMAIN_ID, v));
+ networkRelatedVsdIds.getVsdZoneId().ifPresent(v -> networkDetails.put(NuageVspManager.NETWORK_METADATA_VSD_ZONE_ID, v));
+ }
+ networkRelatedVsdIds.getVsdSubnetId().ifPresent(v -> networkDetails.put(NuageVspManager.NETWORK_METADATA_VSD_SUBNET_ID, v));
+
+ return networkDetails;
+ }
+
+ private static Map<String, String> constructVpcDetails(NetworkRelatedVsdIds networkRelatedVsdIds) {
+ Map<String, String> vpcDetails = Maps.newHashMap();
+
+ networkRelatedVsdIds.getVsdDomainId().ifPresent(v -> vpcDetails.put(NuageVspManager.NETWORK_METADATA_VSD_DOMAIN_ID, v));
+ networkRelatedVsdIds.getVsdZoneId().ifPresent(v -> vpcDetails.put(NuageVspManager.NETWORK_METADATA_VSD_ZONE_ID, v));
+
+ return vpcDetails;
+ }
+
+
@Override
public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException {
if (vm.getType() != VirtualMachine.Type.DomainRouter && _nuageVspEntityBuilder.usesVirtualRouter(network.getNetworkOfferingId())) {
@@ -303,7 +352,7 @@ public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, D
// Make sure the shared network is present
NetworkOffering offering = _ntwkOfferingDao.findById(network.getNetworkOfferingId());
- if (!implement(network.getPhysicalNetworkId(), vspNetwork, _nuageVspEntityBuilder.buildNetworkDhcpOption(network, offering))) {
+ if (!implement(network.getVpcId(), network.getPhysicalNetworkId(), vspNetwork, _nuageVspEntityBuilder.buildNetworkDhcpOption(network, offering))) {
s_logger.error("Failed to implement shared network " + network.getUuid() + " under domain " + context.getDomain().getUuid());
throw new InsufficientVirtualNetworkCapacityException("Failed to implement shared network " + network.getUuid() + " under domain " +
context.getDomain().getUuid(), Network.class, network.getId());
@@ -404,15 +453,12 @@ private void updateDhcpOptionsForExistingVms(Network network, HostVO nuageVspHos
private void checkMultipleSubnetsCombinedWithUseData(Network network) {
if (_ntwkOfferingSrvcDao.listServicesForNetworkOffering(network.getNetworkOfferingId()).contains(Network.Service.UserData.getName())) {
List<VlanVO> vlanVOs = _vlanDao.listVlansByNetworkId(network.getId());
- if (vlanVOs.size() > 1) {
- VlanVO vlanVoItem = vlanVOs.get(0);
- for (VlanVO VlanVoItem2 : FluentIterable.from(vlanVOs).skip(1)) {
- if (!vlanVoItem.equals(VlanVoItem2)
- && !VlanVoItem2.getVlanGateway().equals(vlanVoItem.getVlanGateway())) {
+ if (vlanVOs.stream()
+ .map(VlanVO::getVlanGateway)
+ .distinct()
+ .count() > 1) {
s_logger.error("NuageVsp provider does not support multiple subnets in combination with user data. Network: " + network + ", vlans: " + vlanVOs);
throw new UnsupportedServiceException("NuageVsp provider does not support multiple subnets in combination with user data.");
- }
- }
}
}
}
@@ -422,7 +468,7 @@ protected boolean canHandle(NetworkOffering offering, final NetworkType networkT
if (networkType == NetworkType.Advanced
&& isMyTrafficType(offering.getTrafficType())
&& isMyIsolationMethod(physicalNetwork)
- && (offering.getGuestType() == Network.GuestType.Isolated || offering.getGuestType() == Network.GuestType.Shared)
+ && (offering.getGuestType() == GuestType.Isolated || offering.getGuestType() == GuestType.Shared)
&& hasRequiredServices(offering)) {
if (_configMgr.isOfferingForVpc(offering) && !offering.getIsPersistent()) {
if (s_logger.isDebugEnabled()) {
@@ -578,11 +624,7 @@ private boolean getDefaultHasDns(Map<Long, Boolean> cache, Nic nic) {
? Long.valueOf(nic.getNetworkId())
: getDefaultNetwork(nic.getInstanceId());
- Boolean hasDns = cache.get(networkId);
- if (hasDns == null) {
- hasDns = networkHasDns(_networkDao.findById(networkId));
- cache.put(networkId, hasDns);
- }
+ Boolean hasDns = cache.computeIfAbsent(networkId, k -> networkHasDns(_networkDao.findById(networkId)));
return hasDns;
}
@@ -591,6 +633,4 @@ private Long getDefaultNetwork(long vmId) {
if (defaultNic != null) return defaultNic.getNetworkId();
return null;
}
-
-
}
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/AbstractListener.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/AbstractListener.java
new file mode 100644
index 00000000000..648e0f781e5
--- /dev/null
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/AbstractListener.java
@@ -0,0 +1,91 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package com.cloud.network.manager;
+
+import com.cloud.agent.Listener;
+import com.cloud.agent.api.AgentControlAnswer;
+import com.cloud.agent.api.AgentControlCommand;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.exception.ConnectionException;
+import com.cloud.host.Host;
+import com.cloud.host.Status;
+
+/**
+ * Created by maximusf on 7/19/17.
+ */
+abstract class AbstractListener implements Listener {
+
+ @Override
+ public boolean processAnswers(long agentId, long seq, Answer[] answers) {
+ return true;
+ }
+
+ @Override
+ public boolean processCommands(long agentId, long seq, Command[] commands) {
+ return true;
+ }
+
+ @Override
+ public AgentControlAnswer processControlCommand(long agentId, AgentControlCommand cmd) {
+ return null;
+ }
+
+ @Override
+ public void processHostAdded(long hostId) {
+
+ }
+
+ @Override
+ public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) throws ConnectionException {
+
+ }
+
+ @Override
+ public boolean processDisconnect(long agentId, Status state) {
+ return true;
+ }
+
+ @Override
+ public void processHostAboutToBeRemoved(long hostId) {
+
+ }
+
+ @Override
+ public void processHostRemoved(long hostId, long clusterId) {
+
+ }
+
+ @Override
+ public boolean isRecurring() {
+ return false;
+ }
+
+ @Override
+ public int getTimeout() {
+ return 0;
+ }
+
+ @Override
+ public boolean processTimeout(long agentId, long seq) {
+ return true;
+ }
+}
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManager.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManager.java
index 9f46012dab2..429b11d5967 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManager.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManager.java
@@ -36,21 +36,21 @@
public interface NuageVspManager extends PluggableService {
- static final String nuageVspSharedNetworkOfferingWithSGServiceName = "DefaultNuageVspSharedNetworkOfferingWithSGService";
+ String nuageVspSharedNetworkOfferingWithSGServiceName = "DefaultNuageVspSharedNetworkOfferingWithSGService";
- static final String nuageVPCOfferingName = "Nuage VSP VPC Offering";
+ String nuageVPCOfferingName = "Nuage VSP VPC Offering";
- static final String nuageVPCOfferingDisplayText = "Nuage VSP VPC Offering";
+ String nuageVPCOfferingDisplayText = "Nuage VSP VPC Offering";
- static final String nuageDomainTemplateDetailName = "domainTemplateName";
+ String nuageDomainTemplateDetailName = "domainTemplateName";
- static final String nuageUnderlayVlanIpRangeDetailKey = "nuage.underlay";
+ String nuageUnderlayVlanIpRangeDetailKey = "nuage.underlay";
- static final ConfigKey<Boolean> NuageVspConfigDns = new ConfigKey<Boolean>(Boolean.class, "nuagevsp.configure.dns", "Advanced", "true",
+ ConfigKey<Boolean> NuageVspConfigDns = new ConfigKey<Boolean>(Boolean.class, "nuagevsp.configure.dns", "Advanced", "true",
"Defines if NuageVsp plugin needs to configure DNS setting for a VM or not. True will configure the DNS and false will not configure the DNS settings", true,
Scope.Global, null);
- static final ConfigKey<Boolean> NuageVspDnsExternal = new ConfigKey<Boolean>(
+ ConfigKey<Boolean> NuageVspDnsExternal = new ConfigKey<Boolean>(
Boolean.class,
"nuagevsp.dns.external",
"Advanced",
@@ -61,18 +61,24 @@
+ "If nuagevsp.configure.dns is false, DNS server will not be configured in the VM. Default value for this flag is true",
true, Scope.Global, null);
- static final ConfigKey<String> NuageVspConfigGateway = new ConfigKey<String>(String.class, "nuagevsp.configure.gateway.systemid", "Advanced", "",
+ ConfigKey<String> NuageVspConfigGateway = new ConfigKey<String>(String.class, "nuagevsp.configure.gateway.systemid", "Advanced", "",
"Defines the systemID of the gateway configured in VSP", true, Scope.Global, null);
- static final ConfigKey<String> NuageVspSharedNetworkDomainTemplateName = new ConfigKey<String>(String.class, "nuagevsp.sharedntwk.domaintemplate.name",
+ ConfigKey<String> NuageVspSharedNetworkDomainTemplateName = new ConfigKey<String>(String.class, "nuagevsp.sharedntwk.domaintemplate.name",
"Advanced", "", "Defines if NuageVsp plugin needs to use pre created Domain Template configured in VSP for shared networks", true, Scope.Global, null);
- static final ConfigKey<String> NuageVspVpcDomainTemplateName = new ConfigKey<String>(String.class, "nuagevsp.vpc.domaintemplate.name",
+ ConfigKey<String> NuageVspVpcDomainTemplateName = new ConfigKey<String>(String.class, "nuagevsp.vpc.domaintemplate.name",
"Advanced", "", "Defines if NuageVsp plugin needs to use pre created Domain Template configured in VSP for VPCs", true, Scope.Global, null);
- static final ConfigKey<String> NuageVspIsolatedNetworkDomainTemplateName = new ConfigKey<String>(String.class, "nuagevsp.isolatedntwk.domaintemplate.name",
+ ConfigKey<String> NuageVspIsolatedNetworkDomainTemplateName = new ConfigKey<String>(String.class, "nuagevsp.isolatedntwk.domaintemplate.name",
"Advanced", "", "Defines if NuageVsp plugin needs to use pre created Domain Template configured in VSP for isolated networks", true, Scope.Global, null);
+ String NETWORK_METADATA_VSD_DOMAIN_ID = "vsdDomainId";
+
+ String NETWORK_METADATA_VSD_ZONE_ID = "vsdZoneId";
+
+ String NETWORK_METADATA_VSD_SUBNET_ID = "vsdSubnetId";
+
NuageVspDeviceVO addNuageVspDevice(AddNuageVspDeviceCmd cmd);
NuageVspDeviceVO updateNuageVspDevice(UpdateNuageVspDeviceCmd cmd);
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManagerImpl.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManagerImpl.java
index 3a90163893e..fb79f09b911 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManagerImpl.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManagerImpl.java
@@ -19,17 +19,16 @@
package com.cloud.network.manager;
-import static com.cloud.agent.api.sync.SyncNuageVspCmsIdCommand.SyncType;
-
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
-import java.util.concurrent.ExecutionException;
+import javax.annotation.Nonnull;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
@@ -41,17 +40,19 @@
import net.nuage.vsp.acs.client.common.NuageVspApiVersion;
import net.nuage.vsp.acs.client.common.NuageVspConstants;
+import net.nuage.vsp.acs.client.exception.NuageVspException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import com.google.common.base.MoreObjects;
import com.google.common.base.Strings;
-import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
+import com.google.common.collect.Multimap;
import org.apache.cloudstack.api.ResponseGenerator;
import org.apache.cloudstack.framework.config.ConfigKey;
@@ -59,17 +60,13 @@
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.framework.config.impl.ConfigurationVO;
import org.apache.cloudstack.framework.messagebus.MessageBus;
-import org.apache.cloudstack.framework.messagebus.MessageSubscriber;
import org.apache.cloudstack.network.ExternalNetworkDeviceManager;
import com.cloud.agent.AgentManager;
import com.cloud.agent.Listener;
-import com.cloud.agent.api.AgentControlAnswer;
-import com.cloud.agent.api.AgentControlCommand;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.PingNuageVspCommand;
-import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.manager.CleanUpDomainCommand;
import com.cloud.agent.api.manager.EntityExistsCommand;
import com.cloud.agent.api.manager.GetApiDefaultsAnswer;
@@ -99,7 +96,6 @@
import com.cloud.domain.Domain;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
-import com.cloud.exception.ConnectionException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.host.DetailVO;
import com.cloud.host.Host;
@@ -153,11 +149,13 @@
import com.cloud.utils.fsm.StateListener;
import com.cloud.utils.fsm.StateMachine2;
+import static com.cloud.agent.api.sync.SyncNuageVspCmsIdCommand.SyncType;
+
public class NuageVspManagerImpl extends ManagerBase implements NuageVspManager, Configurable, StateListener<Status, Status.Event, Host> {
private static final Logger s_logger = Logger.getLogger(NuageVspManagerImpl.class);
- public static final Map<Network.Service, Set<Network.Provider>> NUAGE_VSP_VPC_SERVICE_MAP;
+ public static final Multimap<Network.Service, Network.Provider> NUAGE_VSP_VPC_SERVICE_MAP;
private static final ConfigKey[] NUAGE_VSP_CONFIG_KEYS = new ConfigKey<?>[] { NuageVspConfigDns, NuageVspDnsExternal, NuageVspConfigGateway,
NuageVspSharedNetworkDomainTemplateName, NuageVspVpcDomainTemplateName, NuageVspIsolatedNetworkDomainTemplateName };
public static final String CMSID_CONFIG_KEY = "nuagevsp.cms.id";
@@ -222,23 +220,32 @@
Set<Network.Provider> nuageVspProviders = ImmutableSet.of(Network.Provider.NuageVsp);
Set<Network.Provider> vrProviders = ImmutableSet.of(Network.Provider.VPCVirtualRouter);
Set<Network.Provider> lbProviders = ImmutableSet.of(Network.Provider.InternalLbVm);
- NUAGE_VSP_VPC_SERVICE_MAP = ImmutableMap.<Network.Service, Set<Network.Provider>>builder()
- .put(Network.Service.Connectivity, nuageVspProviders)
- .put(Network.Service.Gateway, nuageVspProviders)
- .put(Network.Service.Dhcp, nuageVspProviders)
- .put(Network.Service.StaticNat, nuageVspProviders)
- .put(Network.Service.SourceNat, nuageVspProviders)
- .put(Network.Service.NetworkACL, nuageVspProviders)
- .put(Network.Service.UserData, vrProviders)
- .put(Network.Service.Lb, lbProviders)
- .put(Network.Service.Dns, vrProviders)
+ NUAGE_VSP_VPC_SERVICE_MAP = ImmutableMultimap.<Network.Service, Network.Provider>builder()
+ .putAll(Network.Service.Connectivity, nuageVspProviders)
+ .putAll(Network.Service.Gateway, nuageVspProviders)
+ .putAll(Network.Service.Dhcp, nuageVspProviders)
+ .putAll(Network.Service.StaticNat, nuageVspProviders)
+ .putAll(Network.Service.SourceNat, nuageVspProviders)
+ .putAll(Network.Service.NetworkACL, nuageVspProviders)
+ .putAll(Network.Service.UserData, vrProviders)
+ .putAll(Network.Service.Lb, lbProviders)
+ .putAll(Network.Service.Dns, vrProviders)
.build();
}
+ private Listener _nuageVspResourceListener;
+
@Override
public List<Class<?>> getCommands() {
- return Lists.<Class<?>>newArrayList(AddNuageVspDeviceCmd.class, DeleteNuageVspDeviceCmd.class, ListNuageVspDevicesCmd.class,
- UpdateNuageVspDeviceCmd.class, EnableNuageUnderlayVlanIpRangeCmd.class, DisableNuageUnderlayVlanIpRangeCmd.class, ListNuageUnderlayVlanIpRangesCmd.class);
+ return Lists.<Class<?>>newArrayList(
+ AddNuageVspDeviceCmd.class,
+ DeleteNuageVspDeviceCmd.class,
+ ListNuageVspDevicesCmd.class,
+ UpdateNuageVspDeviceCmd.class,
+ EnableNuageUnderlayVlanIpRangeCmd.class,
+ DisableNuageUnderlayVlanIpRangeCmd.class,
+ ListNuageUnderlayVlanIpRangesCmd.class
+ );
}
@Override
@@ -298,19 +305,15 @@ public NuageVspDeviceVO addNuageVspDevice(AddNuageVspDeviceCmd cmd) {
}
apiVersion = cmd.getApiVersion();
} else {
- boolean apiVersionFound = false;
- Map<NuageVspApiVersion, NuageVspApiVersion.Status> supportedVersions = clientLoader.getNuageVspManagerClient().getSupportedVersions();
- for (NuageVspApiVersion selectedVersion : supportedVersions.keySet()) {
- if (supportedVersions.get(selectedVersion) == NuageVspApiVersion.Status.CURRENT){
- apiVersion = selectedVersion.toString();
- apiVersionFound = true;
- break;
- }
- }
+ List<NuageVspApiVersion> supportedVsdVersions = clientLoader.getNuageVspManagerClient().getSupportedVersionList();
+ supportedVsdVersions.retainAll(Arrays.asList(NuageVspApiVersion.SUPPORTED_VERSIONS));
- if(!apiVersionFound) {
+ if(supportedVsdVersions.isEmpty()) {
throw new CloudRuntimeException("No supported API version found!");
}
+
+ supportedVsdVersions.sort(Comparator.reverseOrder());
+ apiVersion = supportedVsdVersions.get(0).toString();
}
@@ -365,7 +368,7 @@ public NuageVspDeviceVO addNuageVspDevice(AddNuageVspDeviceCmd cmd) {
} catch (ConfigurationException e) {
s_logger.error("Failed to configure Nuage VSD resource " + cmd.getHostName(), e);
throw new CloudRuntimeException("Failed to configure Nuage VSD resource " + cmd.getHostName(), e);
- } catch (ExecutionException ee) {
+ } catch (NuageVspException ee) {
s_logger.error("Failed to add Nuage VSP device " + cmd.getHostName(), ee);
throw new CloudRuntimeException("Failed to add Nuage VSP device " + cmd.getHostName(), ee);
}
@@ -677,7 +680,12 @@ public boolean executeSyncCmsId(NuageVspDeviceVO nuageVspDevice, SyncType syncTy
return answer != null && answer.getSuccess();
}
- private void auditHost(HostVO host) {
+ void auditHost(long hostId) {
+ Host host = _hostDao.findById(hostId);
+ auditHost((HostVO)host);
+ }
+
+ void auditHost(HostVO host) {
if (host == null) return;
_hostDao.loadDetails(host);
@@ -822,7 +830,7 @@ public HostVO getNuageVspHost(long physicalNetworkId) {
PhysicalNetwork physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId);
List<PhysicalNetworkVO> physicalNetworksInZone = _physicalNetworkDao.listByZone(physicalNetwork.getDataCenterId());
for (PhysicalNetworkVO physicalNetworkInZone : physicalNetworksInZone) {
- if (physicalNetworkInZone.getIsolationMethods().contains(PhysicalNetwork.IsolationMethod.VSP.name())) {
+ if (physicalNetworkInZone.getIsolationMethods().contains("VSP")) {
nuageVspDevices = _nuageVspDao.listByPhysicalNetwork(physicalNetworkInZone.getId());
break;
}
@@ -897,124 +905,66 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
@DB
private void initMessageBusListeners() {
// Create corresponding enterprise and profile in VSP when creating a CS Domain
- _messageBus.subscribe(DomainManager.MESSAGE_ADD_DOMAIN_EVENT, new MessageSubscriber() {
- @Override
- public void onPublishMessage(String senderAddress, String subject, Object args) {
- Long domainId = (Long) args;
- Domain domain = _domainDao.findById(domainId);
-
- try {
- _domainDao.acquireInLockTable(domain.getId());
-
- List<NuageVspDeviceVO> nuageVspDevices = _nuageVspDao.listAll();
- for (NuageVspDeviceVO nuageVspDevice : nuageVspDevices) {
- VspDomain vspDomain = _nuageVspEntityBuilder.buildVspDomain(domain);
- SyncDomainCommand cmd = new SyncDomainCommand(vspDomain, SyncDomainCommand.Type.ADD);
- _agentMgr.easySend(nuageVspDevice.getHostId(), cmd);
- }
- } finally {
- _domainDao.releaseFromLockTable(domain.getId());
- }
- }
- });
+ _messageBus.subscribe(DomainManager.MESSAGE_ADD_DOMAIN_EVENT, (senderAddress, subject, args) -> {
+ Long domainId = (Long) args;
+ Domain domain = _domainDao.findById(domainId);
+
+ try {
+ _domainDao.acquireInLockTable(domain.getId());
- // Clean up corresponding resources in VSP when deleting a CS Domain
- _messageBus.subscribe(DomainManager.MESSAGE_PRE_REMOVE_DOMAIN_EVENT, new MessageSubscriber() {
- @Override
- public void onPublishMessage(String senderAddress, String subject, Object args) {
- DomainVO domain = (DomainVO) args;
List<NuageVspDeviceVO> nuageVspDevices = _nuageVspDao.listAll();
for (NuageVspDeviceVO nuageVspDevice : nuageVspDevices) {
- VspDomainCleanUp vspDomainCleanUp = _nuageVspEntityBuilder.buildVspDomainCleanUp(domain);
- CleanUpDomainCommand cmd = new CleanUpDomainCommand(vspDomainCleanUp);
+ VspDomain vspDomain = _nuageVspEntityBuilder.buildVspDomain(domain);
+ SyncDomainCommand cmd = new SyncDomainCommand(vspDomain, SyncDomainCommand.Type.ADD);
_agentMgr.easySend(nuageVspDevice.getHostId(), cmd);
}
+ } finally {
+ _domainDao.releaseFromLockTable(domain.getId());
}
});
- // Delete corresponding enterprise and profile in VSP when deleting a CS Domain
- _messageBus.subscribe(DomainManager.MESSAGE_REMOVE_DOMAIN_EVENT, new MessageSubscriber() {
- @Override
- public void onPublishMessage(String senderAddress, String subject, Object args) {
- DomainVO domain = (DomainVO) args;
- List<NuageVspDeviceVO> nuageVspDevices = _nuageVspDao.listAll();
- for (NuageVspDeviceVO nuageVspDevice : nuageVspDevices) {
- VspDomain vspDomain = _nuageVspEntityBuilder.buildVspDomain(domain);
- SyncDomainCommand syncCmd = new SyncDomainCommand(vspDomain, SyncDomainCommand.Type.REMOVE);
- _agentMgr.easySend(nuageVspDevice.getHostId(), syncCmd);
- }
+ // Clean up corresponding resources in VSP when deleting a CS Domain
+ _messageBus.subscribe(DomainManager.MESSAGE_PRE_REMOVE_DOMAIN_EVENT, (senderAddress, subject, args) -> {
+ DomainVO domain = (DomainVO) args;
+ List<NuageVspDeviceVO> nuageVspDevices = _nuageVspDao.listAll();
+ for (NuageVspDeviceVO nuageVspDevice : nuageVspDevices) {
+ VspDomainCleanUp vspDomainCleanUp = _nuageVspEntityBuilder.buildVspDomainCleanUp(domain);
+ CleanUpDomainCommand cmd = new CleanUpDomainCommand(vspDomainCleanUp);
+ _agentMgr.easySend(nuageVspDevice.getHostId(), cmd);
}
});
- }
- @DB
- private void initNuageVspResourceListeners() {
- _agentMgr.registerForHostEvents(new Listener() {
- @Override
- public boolean processAnswers(long agentId, long seq, Answer[] answers) {
- return true;
+ // Delete corresponding enterprise and profile in VSP when deleting a CS Domain
+ _messageBus.subscribe(DomainManager.MESSAGE_REMOVE_DOMAIN_EVENT, (senderAddress, subject, args) -> {
+ DomainVO domain = (DomainVO) args;
+ List<NuageVspDeviceVO> nuageVspDevices = _nuageVspDao.listAll();
+ for (NuageVspDeviceVO nuageVspDevice : nuageVspDevices) {
+ VspDomain vspDomain = _nuageVspEntityBuilder.buildVspDomain(domain);
+ SyncDomainCommand syncCmd = new SyncDomainCommand(vspDomain, SyncDomainCommand.Type.REMOVE);
+ _agentMgr.easySend(nuageVspDevice.getHostId(), syncCmd);
}
+ });
+ }
- @Override
- public boolean processCommands(long agentId, long seq, Command[] commands) {
- if (commands != null && commands.length == 1) {
- Command command = commands[0];
- if (command instanceof PingNuageVspCommand) {
- PingNuageVspCommand pingNuageVspCommand = (PingNuageVspCommand) command;
- if (pingNuageVspCommand.shouldAudit()) {
- Host host = _hostDao.findById(pingNuageVspCommand.getHostId());
- auditHost((HostVO) host);
- }
+ private class NuageVspResourceListener extends AbstractListener {
+ @Override
+ public boolean processCommands(long agentId, long seq, Command[] commands) {
+ if (commands != null && commands.length == 1) {
+ Command command = commands[0];
+ if (command instanceof PingNuageVspCommand) {
+ PingNuageVspCommand pingNuageVspCommand = (PingNuageVspCommand)command;
+ if (pingNuageVspCommand.shouldAudit()) {
+ auditHost(pingNuageVspCommand.getHostId());
}
}
- return true;
- }
-
- @Override
- public AgentControlAnswer processControlCommand(long agentId, AgentControlCommand cmd) {
- return null;
- }
-
- @Override
- public void processHostAdded(long hostId) {
-
- }
-
- @Override
- public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) throws ConnectionException {
-
- }
-
- @Override
- public boolean processDisconnect(long agentId, Status state) {
- return true;
- }
-
- @Override
- public void processHostAboutToBeRemoved(long hostId) {
-
- }
-
- @Override
- public void processHostRemoved(long hostId, long clusterId) {
-
- }
-
- @Override
- public boolean isRecurring() {
- return false;
- }
-
- @Override
- public int getTimeout() {
- return 0;
}
+ return true;
+ }
+ }
- @Override
- public boolean processTimeout(long agentId, long seq) {
- return true;
- }
- }, false, true, false);
+ @DB
+ private void initNuageVspResourceListeners() {
+ _agentMgr.registerForHostEvents(new NuageVspResourceListener(), false, true, false);
}
@DB
@@ -1070,79 +1020,74 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
}
@DB
- protected VpcOffering createVpcOffering(final String name, final String displayText, final Map<Network.Service, Set<Network.Provider>> svcProviderMap, final boolean isDefault,
+ protected VpcOffering createVpcOffering(final String name, final String displayText, final Multimap<Network.Service, Network.Provider> svcProviderMap, final boolean isDefault,
final VpcOffering.State state, final Long serviceOfferingId) {
- return Transaction.execute(new TransactionCallback<VpcOffering>() {
- @Override
- public VpcOffering doInTransaction(TransactionStatus status) {
- // create vpc offering object
- VpcOfferingVO offering = new VpcOfferingVO(name, displayText, isDefault, serviceOfferingId, false, false);
+ return Transaction.execute((TransactionCallback<VpcOffering>)status -> createVpcOfferingInTransaction(name, displayText, svcProviderMap, isDefault, state, serviceOfferingId));
+ }
- if (state != null) {
- offering.setState(state);
- }
- if (s_logger.isDebugEnabled()) {
- s_logger.debug(String.format("Adding vpc offering %s", offering));
- }
- offering = _vpcOffDao.persist(offering);
- // populate services and providers
- if (svcProviderMap != null) {
- for (Network.Service service : svcProviderMap.keySet()) {
- Set<Network.Provider> providers = svcProviderMap.get(service);
- if (providers != null && !providers.isEmpty()) {
- for (Network.Provider provider : providers) {
- VpcOfferingServiceMapVO offService = new VpcOfferingServiceMapVO(offering.getId(), service, provider);
- _vpcOffSvcMapDao.persist(offService);
- if (s_logger.isTraceEnabled()) {
- s_logger.trace(String.format("Added service for the vpc offering: %s with provider %s", offService, provider.getName()));
- }
- }
- } else {
- throw new InvalidParameterValueException(String.format("Provider is missing for the VPC offering service %s", service.getName()));
- }
- }
+ private VpcOffering createVpcOfferingInTransaction(String name, String displayText, Multimap<Network.Service, Network.Provider> svcProviderMap, boolean isDefault,
+ VpcOffering.State state, Long serviceOfferingId) {
+ // create vpc offering object
+ VpcOfferingVO offering = new VpcOfferingVO(name, displayText, isDefault, serviceOfferingId, false, false);
+
+ if (state != null) {
+ offering.setState(state);
+ }
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug(String.format("Adding vpc offering %s", offering));
+ }
+ offering = _vpcOffDao.persist(offering);
+ // populate services and providers
+ if (svcProviderMap != null) {
+ for (Map.Entry<Network.Service, Network.Provider> entry : svcProviderMap.entries()) {
+ Network.Service service = entry.getKey();
+ Network.Provider provider = entry.getValue();
+
+ VpcOfferingServiceMapVO offService = new VpcOfferingServiceMapVO(offering.getId(), service, provider);
+ _vpcOffSvcMapDao.persist(offService);
+ if (s_logger.isTraceEnabled()) {
+ s_logger.trace(String.format("Added service for the vpc offering: %s with provider %s", offService, provider.getName()));
}
- return offering;
}
- });
+ }
+
+ return offering;
}
@DB
- protected void updateVpcOffering(final VpcOffering offering, final Map<Network.Service, Set<Network.Provider>> svcProviderMap) {
- Transaction.execute(new TransactionCallback<VpcOffering>() {
- @Override
- public VpcOffering doInTransaction(TransactionStatus status) {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug(String.format("Updating vpc offering %s", offering));
- }
+ protected void updateVpcOffering(final VpcOffering offering, final Multimap<Network.Service, Network.Provider> svcProviderMap) {
+ Transaction.execute((TransactionCallback<VpcOffering>)status -> updateVpcOfferingInTransaction(offering, svcProviderMap));
+ }
- List<VpcOfferingServiceMapVO> currentVpcOfferingServices = _vpcOffSvcMapDao.listByVpcOffId(offering.getId());
- Map<Network.Service, Set<Network.Provider>> currentSvcProviderMap = Maps.newHashMap();
- for (VpcOfferingServiceMapVO vpcOfferingService : currentVpcOfferingServices) {
- Network.Service service = Network.Service.getService(vpcOfferingService.getService());
- Network.Provider provider = Network.Provider.getProvider(vpcOfferingService.getProvider());
+ @Nonnull
+ private VpcOffering updateVpcOfferingInTransaction(VpcOffering offering, Multimap<Network.Service, Network.Provider> svcProviderMap) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug(String.format("Updating vpc offering %s", offering));
+ }
- if (!currentSvcProviderMap.containsKey(service)) {
- currentSvcProviderMap.put(service, Sets.newHashSet(provider));
- } else if (!currentSvcProviderMap.get(service).contains(provider)) {
- currentSvcProviderMap.get(service).add(provider);
- }
- }
+ List<VpcOfferingServiceMapVO> currentVpcOfferingServices = _vpcOffSvcMapDao.listByVpcOffId(offering.getId());
+ Multimap<Network.Service, Network.Provider> currentSvcProviderMap = HashMultimap.create();
+ for (VpcOfferingServiceMapVO vpcOfferingService : currentVpcOfferingServices) {
+ Network.Service service = Network.Service.getService(vpcOfferingService.getService());
+ Network.Provider provider = Network.Provider.getProvider(vpcOfferingService.getProvider());
+ currentSvcProviderMap.put(service, provider);
+ }
- for (Network.Service service : svcProviderMap.keySet()) {
- for (Network.Provider provider : svcProviderMap.get(service)) {
- if (currentSvcProviderMap.get(service) == null || !currentSvcProviderMap.get(service).contains(provider)) {
- VpcOfferingServiceMapVO offService = new VpcOfferingServiceMapVO(offering.getId(), service, provider);
- _vpcOffSvcMapDao.persist(offService);
- if (s_logger.isDebugEnabled()) {
- s_logger.debug(String.format("Added service for the vpc offering: %s", offService));
- }
- }
- }
+ for (Map.Entry<Network.Service, Network.Provider> entry : svcProviderMap.entries()) {
+ Network.Service service = entry.getKey();
+ Network.Provider provider = entry.getValue();
+
+ if (!currentSvcProviderMap.containsEntry(service, provider)) {
+ VpcOfferingServiceMapVO offService = new VpcOfferingServiceMapVO(offering.getId(), service, provider);
+ _vpcOffSvcMapDao.persist(offService);
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug(String.format("Added service for the vpc offering: %s", offService));
}
- return offering;
}
- });
+
+ }
+
+ return offering;
}
private HostVO findNuageVspHost(long hostId) {
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/NuageVspResource.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/NuageVspResource.java
index 5ffe683e500..72ff5b016b4 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/NuageVspResource.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/NuageVspResource.java
@@ -20,7 +20,8 @@
package com.cloud.network.resource;
import java.util.Map;
-import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.Collectors;
import javax.naming.ConfigurationException;
@@ -31,6 +32,8 @@
import net.nuage.vsp.acs.client.api.NuageVspManagerClient;
import net.nuage.vsp.acs.client.api.NuageVspPluginClientLoader;
import net.nuage.vsp.acs.client.api.model.VspHost;
+import net.nuage.vsp.acs.client.common.RequestType;
+import net.nuage.vsp.acs.client.common.model.NuageVspEntity;
import net.nuage.vsp.acs.client.exception.NuageVspException;
import org.apache.log4j.Logger;
@@ -48,8 +51,9 @@
import com.cloud.resource.ServerResource;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.mgmt.JmxUtil;
-public class NuageVspResource extends ManagerBase implements ServerResource {
+public class NuageVspResource extends ManagerBase implements ServerResource, VspStatisticsMBean {
private static final Logger s_logger = Logger.getLogger(NuageVspResource.class);
private String _guid;
@@ -73,7 +77,7 @@ public VspHost validate(NuageVspResourceConfiguration configuration) throws Conf
if (!newVspHost.getApiVersion().isSupported()) {
- s_logger.warn(String.format("[UPGRADE] API version %s of Nuage Vsp Device %s should be updated.", _vspHost.getApiVersion(), configuration.hostName()));
+ s_logger.warn(String.format("[UPGRADE] API version %s of Nuage Vsp Device %s should be updated.", newVspHost.getApiVersion(), configuration.hostName()));
}
_guid = configuration.guid();
@@ -87,7 +91,7 @@ public VspHost validate(NuageVspResourceConfiguration configuration) throws Conf
_vspHost = newVspHost;
_clientLoader = clientLoader;
- } catch (ExecutionException e) {
+ } catch (NuageVspException e) {
s_logger.error(e.getMessage(), e);
throw new CloudRuntimeException(e.getMessage(), e);
}
@@ -95,6 +99,64 @@ public VspHost validate(NuageVspResourceConfiguration configuration) throws Conf
return _vspHost;
}
+ @Override
+ public long getVSDStatistics() {
+ return _clientLoader.getNuageVspStatistics().getVsdCount();
+ }
+
+
+ @Override
+ public long getVsdStatisticsByEntityType(String entity) {
+ try {
+ NuageVspEntity nuageVspEntity = NuageVspEntity.valueOf(entity);
+ return _clientLoader.getNuageVspStatistics().getVsdCount(nuageVspEntity);
+ } catch (IllegalArgumentException e) {
+ return -1;
+ }
+ }
+
+ @Override
+ public long getVsdStatisticsByRequestType(String requestType) {
+ try {
+ RequestType requestTypeValue = RequestType.valueOf(requestType);
+ return _clientLoader.getNuageVspStatistics().getVsdCount(requestTypeValue);
+ } catch (IllegalArgumentException e) {
+ return -1;
+ }
+
+ }
+
+ @Override
+ public long getVsdStatisticsByEntityAndRequestType(String entity, String requestType) {
+ try {
+ RequestType requestTypeValue = RequestType.valueOf(requestType);
+ NuageVspEntity nuageVspEntity = NuageVspEntity.valueOf(entity);
+ return _clientLoader.getNuageVspStatistics().getVsdCount(nuageVspEntity, requestTypeValue);
+ } catch (IllegalArgumentException e) {
+ return -1;
+ }
+ }
+
+ private static Map<String, AtomicLong> convertHashMap(Map<RequestType, AtomicLong> map) {
+ return map.entrySet()
+ .stream()
+ .collect(Collectors.toMap(
+ e -> e.getKey().toString(),
+ Map.Entry::getValue)
+ );
+ }
+
+ @Override
+ public Map<String, Map<String, AtomicLong>> getVsdStatisticsReport() {
+ return _clientLoader.getNuageVspStatistics()
+ .getVsdCountReport()
+ .entrySet().stream()
+ .collect(Collectors.toMap(
+ e -> e.getKey().toString(),
+ e -> convertHashMap(e.getValue())
+ ));
+ }
+
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
if(super.configure(name, params)) {
@@ -113,11 +175,25 @@ protected NuageVspPluginClientLoader getClientLoader(VspHost vspHost) {
@Override
public boolean start() {
+ try {
+ JmxUtil.registerMBean("NuageVspResource", _name, new VspStatisticsMBeanImpl(this));
+ } catch (Exception e) {
+ s_logger.warn("Unable to initialize statistics Mbean", e);
+ }
+
return true;
+
}
@Override
public boolean stop() {
+
+ try {
+ JmxUtil.unregisterMBean("NuageVspResource", _name);
+ } catch (Exception e) {
+ s_logger.warn("Unable to initialize inaccurate clock", e);
+ }
+
return true;
}
@@ -155,7 +231,7 @@ public PingCommand getCurrentStatus(long id) {
try {
login();
- } catch (ExecutionException | ConfigurationException e) {
+ } catch (NuageVspException | ConfigurationException e) {
s_logger.error("Failed to ping to Nuage VSD on " + _name + " as user " +_vspHost.getCmsUserLogin(), e);
_shouldAudit = true;
return null;
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/NuageVspResourceConfiguration.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/NuageVspResourceConfiguration.java
index 1861941179c..71d7390a668 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/NuageVspResourceConfiguration.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/NuageVspResourceConfiguration.java
@@ -25,7 +25,6 @@
import javax.naming.ConfigurationException;
-import com.google.common.base.Preconditions;
import net.nuage.vsp.acs.client.api.model.NuageVspUser;
import net.nuage.vsp.acs.client.api.model.VspHost;
import net.nuage.vsp.acs.client.common.NuageVspApiVersion;
@@ -34,6 +33,8 @@
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
+import com.google.common.base.Preconditions;
+
import com.cloud.util.NuageVspUtil;
public class NuageVspResourceConfiguration {
@@ -265,7 +266,7 @@ public void validate() throws ConfigurationException {
verifyNotEmpty("API version", _apiVersion);
try {
- new NuageVspApiVersion(_apiVersion);
+ NuageVspApiVersion.fromString(_apiVersion);
} catch(IllegalArgumentException e) {
throw new ConfigurationException("Incorrect API version");
}
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/VspStatisticsMBean.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/VspStatisticsMBean.java
new file mode 100644
index 00000000000..55072ec6650
--- /dev/null
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/VspStatisticsMBean.java
@@ -0,0 +1,66 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package com.cloud.network.resource;
+
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
+
+import com.cloud.utils.mgmt.ManagementBean;
+
+/**
+ * Created by sgoeminn on 1/24/17.
+ */
+public interface VspStatisticsMBean extends ManagementBean {
+
+ /**
+ * Returns the global count of all the VSD calls since start up
+ * @return
+ */
+ long getVSDStatistics();
+
+ /**
+ * Returns the count of all the vsd calls where the entityType is equal to the entity
+ * @param entity
+ * @return
+ */
+ long getVsdStatisticsByEntityType(String entity);
+
+ /**
+ * Returns the count of all the vsd calls where the requestType is equal to the requestType
+ * @param requestType
+ * @return
+ */
+ long getVsdStatisticsByRequestType(String requestType);
+
+ /**
+ * Returns the count of all the vsd calls where the EntityType is equal to the entity
+ * and the RequestType is equal to the requestType string.
+ * @param entity
+ * @param requestType
+ * @return
+ */
+ long getVsdStatisticsByEntityAndRequestType(String entity, String requestType);
+
+ /**
+ * Returns the count of all VSD calls with EntityType entity and RequestType type
+ * @return
+ */
+ Map<String, Map<String, AtomicLong>> getVsdStatisticsReport();
+}
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/VspStatisticsMBeanImpl.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/VspStatisticsMBeanImpl.java
new file mode 100644
index 00000000000..7e3de561db1
--- /dev/null
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/VspStatisticsMBeanImpl.java
@@ -0,0 +1,66 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package com.cloud.network.resource;
+
+import javax.management.StandardMBean;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * Created by sgoeminn on 1/24/17.
+ */
+public class VspStatisticsMBeanImpl extends StandardMBean implements VspStatisticsMBean{
+ private VspStatisticsMBean _delegate;
+
+ public VspStatisticsMBeanImpl(VspStatisticsMBean nuageVspResource) {
+ super(VspStatisticsMBean.class, false);
+ _delegate = nuageVspResource;
+ }
+
+ @Override
+ public long getVSDStatistics() {
+ return _delegate.getVSDStatistics();
+ }
+
+ @Override
+ public long getVsdStatisticsByEntityType(String entity) {
+ return _delegate.getVsdStatisticsByEntityType(entity);
+ }
+
+ @Override
+ public long getVsdStatisticsByRequestType(String requestType) {
+ return _delegate.getVsdStatisticsByRequestType(requestType);
+ }
+
+ @Override
+ public long getVsdStatisticsByEntityAndRequestType(String entity, String requestType) {
+ return _delegate.getVsdStatisticsByEntityAndRequestType(entity, requestType);
+ }
+
+ @Override
+ public Map<String, Map<String, AtomicLong>> getVsdStatisticsReport() {
+ return _delegate.getVsdStatisticsReport();
+ }
+
+ @Override
+ public String getName() {
+ return _delegate.getName();
+ }
+}
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/vsp/resource/wrapper/NuageVspGuruImplementNetworkCommandWrapper.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/vsp/resource/wrapper/NuageVspGuruImplementNetworkCommandWrapper.java
index 1ba77ff2bd0..1e57e244e65 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/network/vsp/resource/wrapper/NuageVspGuruImplementNetworkCommandWrapper.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/vsp/resource/wrapper/NuageVspGuruImplementNetworkCommandWrapper.java
@@ -21,22 +21,27 @@
import javax.naming.ConfigurationException;
+import net.nuage.vsp.acs.client.api.NuageVspGuruClient;
+import net.nuage.vsp.acs.client.api.model.NetworkRelatedVsdIds;
import net.nuage.vsp.acs.client.exception.NuageVspException;
import com.cloud.agent.api.guru.ImplementNetworkVspCommand;
+import com.cloud.agent.api.manager.ImplementNetworkVspAnswer;
import com.cloud.network.resource.NuageVspResource;
+import com.cloud.resource.CommandWrapper;
import com.cloud.resource.ResourceWrapper;
@ResourceWrapper(handles = ImplementNetworkVspCommand.class)
-public final class NuageVspGuruImplementNetworkCommandWrapper extends NuageVspCommandWrapper<ImplementNetworkVspCommand> {
-
- @Override public boolean executeNuageVspCommand(ImplementNetworkVspCommand cmd, NuageVspResource nuageVspResource) throws ConfigurationException, NuageVspException {
- nuageVspResource.getNuageVspGuruClient().implement(cmd.getNetwork(), cmd.getDhcpOption());
- return true;
- }
-
- @Override public StringBuilder fillDetail(StringBuilder stringBuilder, ImplementNetworkVspCommand command) {
- return stringBuilder.append("Created network mapping to ").append(command.getNetwork().getName());
+public final class NuageVspGuruImplementNetworkCommandWrapper extends CommandWrapper<ImplementNetworkVspCommand, ImplementNetworkVspAnswer, NuageVspResource> {
+
+ @Override
+ public ImplementNetworkVspAnswer execute(ImplementNetworkVspCommand command, NuageVspResource serverResource) {
+ try {
+ NuageVspGuruClient client = serverResource.getNuageVspGuruClient();
+ NetworkRelatedVsdIds networkRelatedVsdIds = client.implement(command.getNetwork(), command.getDhcpOption());
+ return new ImplementNetworkVspAnswer(command, networkRelatedVsdIds);
+ } catch (ConfigurationException | NuageVspException e) {
+ return new ImplementNetworkVspAnswer(command, e);
+ }
}
-
}
\ No newline at end of file
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/util/NuageVspEntityBuilder.java b/plugins/network-elements/nuage-vsp/src/com/cloud/util/NuageVspEntityBuilder.java
index 4e6ccb3e64e..9b0e0d93213 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/util/NuageVspEntityBuilder.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/util/NuageVspEntityBuilder.java
@@ -25,14 +25,32 @@
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
+import java.util.stream.Collectors;
-import javax.annotation.Nullable;
import javax.inject.Inject;
-import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import net.nuage.vsp.acs.client.api.model.NetworkRelatedVsdIds;
+import net.nuage.vsp.acs.client.api.model.VspAclRule;
+import net.nuage.vsp.acs.client.api.model.VspAddressRange;
+import net.nuage.vsp.acs.client.api.model.VspDhcpDomainOption;
+import net.nuage.vsp.acs.client.api.model.VspDhcpVMOption;
+import net.nuage.vsp.acs.client.api.model.VspDomain;
+import net.nuage.vsp.acs.client.api.model.VspDomainCleanUp;
+import net.nuage.vsp.acs.client.api.model.VspNetwork;
+import net.nuage.vsp.acs.client.api.model.VspNic;
+import net.nuage.vsp.acs.client.api.model.VspStaticNat;
+import net.nuage.vsp.acs.client.api.model.VspVm;
+import net.nuage.vsp.acs.client.common.model.Pair;
+
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+
import com.cloud.dc.Vlan;
import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.VlanDao;
@@ -65,24 +83,12 @@
import com.cloud.vm.NicVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.dao.NicDao;
+import com.cloud.vm.dao.NicSecondaryIpDao;
+import com.cloud.vm.dao.NicSecondaryIpVO;
import com.cloud.vm.dao.VMInstanceDao;
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-import net.nuage.vsp.acs.client.api.model.VspAclRule;
-import net.nuage.vsp.acs.client.api.model.VspAddressRange;
-import net.nuage.vsp.acs.client.api.model.VspDhcpDomainOption;
-import net.nuage.vsp.acs.client.api.model.VspDhcpVMOption;
-import net.nuage.vsp.acs.client.api.model.VspDomain;
-import net.nuage.vsp.acs.client.api.model.VspDomainCleanUp;
-import net.nuage.vsp.acs.client.api.model.VspNetwork;
-import net.nuage.vsp.acs.client.api.model.VspNic;
-import net.nuage.vsp.acs.client.api.model.VspStaticNat;
-import net.nuage.vsp.acs.client.api.model.VspVm;
-import net.nuage.vsp.acs.client.common.model.Pair;
+import org.apache.cloudstack.resourcedetail.dao.VpcDetailsDao;
+import org.apache.commons.collections.MapUtils;
public class NuageVspEntityBuilder {
private static final Logger s_logger = Logger.getLogger(NuageVspEntityBuilder.class);
@@ -112,10 +118,16 @@
@Inject
NetworkDetailsDao _networkDetailsDao;
@Inject
+ VpcDetailsDao _vpcDetailsDao;
+ @Inject
VMInstanceDao _vmInstanceDao;
@Inject
NuageVspManager _nuageVspManager;
@Inject
+ NicDao _nicDao;
+ @Inject
+ NicSecondaryIpDao _nicSecondaryIpDao;
+ @Inject
NetworkOfferingServiceMapDao _ntwkOfferingSrvcDao;
@@ -151,6 +163,7 @@ public VspNetwork buildVspNetwork(Network network) {
return buildVspNetwork(network.getDomainId(), network);
}
+ //TODO:Sigert implement caching in this function. retrieve data
public VspNetwork buildVspNetwork(long domainId, Network network) {
VspNetwork.Builder vspNetworkBuilder = new VspNetwork.Builder()
.id(network.getId())
@@ -171,31 +184,60 @@ public VspNetwork buildVspNetwork(long domainId, Network network) {
NetworkOfferingVO networkOffering = _networkOfferingDao.findById(network.getNetworkOfferingId());
vspNetworkBuilder.egressDefaultPolicy(networkOffering.getEgressDefaultPolicy()).publicAccess(networkOffering.getSupportsPublicAccess());
+ Map<String, String> networkDetails = _networkDetailsDao.listDetailsKeyPairs(network.getId(), false);
+ String vsdSubnetId = null;
+ String vsdZoneId = null;
+ String vsdDomainId = null;
+
+ if (MapUtils.isNotEmpty(networkDetails)) {
+ vsdSubnetId = networkDetails.get(NuageVspManager.NETWORK_METADATA_VSD_SUBNET_ID);
+ }
+
if (network.getVpcId() != null) {
- VpcVO vpc = _vpcDao.findById(network.getVpcId());
+ long vpcId = network.getVpcId();
+ VpcVO vpc = _vpcDao.findById(vpcId);
vspNetworkBuilder.vpcUuid(vpc.getUuid())
.vpcName(vpc.getName())
.networkType(VspNetwork.NetworkType.Vpc);
+ Map<String, String> vpcDetails = _vpcDetailsDao.listDetailsKeyPairs(vpcId, false);
+ if (MapUtils.isNotEmpty(vpcDetails)) {
+ vsdDomainId = vpcDetails.get(NuageVspManager.NETWORK_METADATA_VSD_DOMAIN_ID);
+ vsdZoneId = vpcDetails.get(NuageVspManager.NETWORK_METADATA_VSD_ZONE_ID);
+ }
+
} else {
+ if (MapUtils.isNotEmpty(networkDetails)) {
+ vsdDomainId = networkDetails.get(NuageVspManager.NETWORK_METADATA_VSD_DOMAIN_ID);
+ vsdZoneId = networkDetails.get(NuageVspManager.NETWORK_METADATA_VSD_ZONE_ID);
+ }
+
if (networkOffering.getGuestType() == Network.GuestType.Shared) {
List<VlanVO> vlans = _vlanDao.listVlansByNetworkIdIncludingRemoved(network.getId());
- List<VspAddressRange> vspAddressRanges = Lists.transform(vlans, new Function<VlanVO, VspAddressRange>() {
- @Nullable
- @Override
- public VspAddressRange apply(VlanVO vlanVO) {
- return new VspAddressRange.Builder().gateway(vlanVO.getVlanGateway()).netmask(vlanVO.getVlanNetmask()).build();
- }
- });
-
- vspNetworkBuilder.networkType(VspNetwork.NetworkType.Shared).addressRanges(vspAddressRanges);
+
+ List<VspAddressRange> vspAddressRanges =
+ vlans.stream()
+ .map(vlan -> new VspAddressRange.Builder().gateway(vlan.getVlanGateway()).netmask(vlan.getVlanNetmask()).build())
+ .collect(Collectors.toList());
+
+
+ vspNetworkBuilder.networkType(VspNetwork.NetworkType.Shared)
+ .addressRanges(vspAddressRanges);
} else if (_networkOfferingServiceMapDao.areServicesSupportedByNetworkOffering(network.getNetworkOfferingId(), Network.Service.SourceNat)
|| _networkOfferingServiceMapDao.areServicesSupportedByNetworkOffering(network.getNetworkOfferingId(), Network.Service.StaticNat)) {
vspNetworkBuilder.networkType(VspNetwork.NetworkType.L3);
} else {
vspNetworkBuilder.networkType(VspNetwork.NetworkType.L2);
}
+
}
+ NetworkRelatedVsdIds networkRelatedVsdIds = new NetworkRelatedVsdIds.Builder()
+ .vsdDomainId(vsdDomainId)
+ .vsdSubnetId(vsdSubnetId)
+ .vsdZoneId(vsdZoneId)
+ .build();
+ vspNetworkBuilder.networkRelatedVsdIds(networkRelatedVsdIds);
+
boolean firewallServiceSupported = _networkModel.areServicesSupportedByNetworkOffering(network.getNetworkOfferingId(), Network.Service.Firewall);
vspNetworkBuilder.firewallServiceSupported(firewallServiceSupported);
@@ -225,15 +267,10 @@ public boolean usesVirtualRouter(long networkOfferingId) {
public VspNetwork updateVspNetworkByPublicIp(VspNetwork vspNetwork, Network network, String publicIp) {
List<VlanVO> vlans = _vlanDao.listVlansByNetworkId(network.getId());
final long ip = NetUtils.ip2Long(publicIp);
- VlanVO matchingVlan = Iterables.find(vlans, new Predicate<VlanVO>() {
- @Override
- public boolean apply(@Nullable VlanVO vlan) {
- Pair<String, String> ipAddressRange = getIpAddressRange(vlan);
- long startIp = NetUtils.ip2Long(ipAddressRange.getLeft());
- long endIp = NetUtils.ip2Long(ipAddressRange.getRight());
- return startIp <= ip && ip <= endIp;
- }
- });
+ VlanVO matchingVlan = vlans.stream()
+ .filter(vlan -> isVlanContainingIp(vlan, ip))
+ .findFirst()
+ .get();
return new VspNetwork.Builder().fromObject(vspNetwork)
.gateway(matchingVlan.getVlanGateway())
@@ -241,6 +278,13 @@ public boolean apply(@Nullable VlanVO vlan) {
.build();
}
+ private boolean isVlanContainingIp(Vlan vlan, long ip) {
+ Pair<String, String> ipAddressRange = getIpAddressRange(vlan);
+ long startIp = NetUtils.ip2Long(ipAddressRange.getLeft());
+ long endIp = NetUtils.ip2Long(ipAddressRange.getRight());
+ return startIp <= ip && ip <= endIp;
+ }
+
private List<Pair<String, String>> getSharedIpAddressRanges(long networkId) {
List<VlanVO> vlans = _vlanDao.listVlansByNetworkId(networkId);
List<Pair<String, String>> ipAddressRanges = Lists.newArrayList();
@@ -326,30 +370,8 @@ private String getVirtualRouterIP(Network network, List<Pair<String, String>> ip
public VspVm buildVspVm(VirtualMachine vm, Network network) {
VspVm.Builder vspVmBuilder = new VspVm.Builder()
.uuid(vm.getUuid())
- .name(vm.getInstanceName());
-
- switch (vm.getState()) {
- case Starting:
- vspVmBuilder.state(VspVm.State.Starting); break;
- case Running:
- vspVmBuilder.state(VspVm.State.Running); break;
- case Stopping:
- vspVmBuilder.state(VspVm.State.Stopping); break;
- case Stopped:
- vspVmBuilder.state(VspVm.State.Stopped); break;
- case Destroyed:
- vspVmBuilder.state(VspVm.State.Destroyed); break;
- case Expunging:
- vspVmBuilder.state(VspVm.State.Expunging); break;
- case Migrating:
- vspVmBuilder.state(VspVm.State.Migrating); break;
- case Error:
- vspVmBuilder.state(VspVm.State.Error); break;
- case Shutdowned:
- vspVmBuilder.state(VspVm.State.Shutdowned); break;
- default:
- vspVmBuilder.state(VspVm.State.Unknown);
- }
+ .name(vm.getInstanceName())
+ .state(getEnumValue(vm.getState(), VspVm.State.Unknown));
boolean isDomainRouter = vm.getType().equals(VirtualMachine.Type.DomainRouter);
vspVmBuilder.domainRouter(isDomainRouter);
@@ -363,20 +385,28 @@ public VspVm buildVspVm(VirtualMachine vm, Network network) {
}
public VspNic buildVspNic(String nicUuid, NicProfile nicProfile) {
- return buildVspNic(nicUuid, nicProfile.getMacAddress(), nicProfile.getIPv4Address(), nicProfile.getNetworkId());
+ return buildVspNic(nicUuid, nicProfile.getMacAddress(), nicProfile.getIPv4Address(), nicProfile.getNetworkId(), null);
}
public VspNic buildVspNic(NicVO nic) {
- return buildVspNic(nic.getUuid(), nic.getMacAddress(), nic.getIPv4Address(), nic.getNetworkId());
+ return buildVspNic(nic.getUuid(), nic.getMacAddress(), nic.getIPv4Address(), nic.getNetworkId(), null);
+ }
+
+ public VspNic buildVspNic(NicVO nic, NicSecondaryIpVO nicSecondaryIp) {
+ return buildVspNic(nic.getUuid(), nic.getMacAddress(), nic.getIPv4Address(), nic.getNetworkId(), nicSecondaryIp);
}
- private VspNic buildVspNic(String uuid, String macAddress, String ip, long networkId) {
+ private VspNic buildVspNic(String uuid, String macAddress, String ip, long networkId, NicSecondaryIpVO nicSecondaryIp) {
VspNic.Builder vspNicBuilder = new VspNic.Builder()
.uuid(uuid)
.macAddress(macAddress)
.useStaticIp(true)
.ip(ip);
+ if (nicSecondaryIp != null) {
+ vspNicBuilder.secondaryIpUuid(nicSecondaryIp.getUuid()).secondaryIpAddress(nicSecondaryIp.getIp4Address());
+ }
+
Network network = _networkDao.findById(networkId);
NetworkOffering networkOffering = _networkOfferingDao.findById(network.getNetworkOfferingId());
@@ -395,6 +425,10 @@ public VspStaticNat buildVspStaticNat(Boolean forRevoke, IPAddressVO staticNatIp
.vlanNetmask(staticNatVlan.getVlanNetmask())
.vlanUnderlay(NuageVspUtil.isUnderlayEnabledForVlan(_vlanDetailsDao, staticNatVlan));
+ if (staticNatIp.getVmIp() != null) {
+ vspStaticNatBuilder.destinationIp(staticNatIp.getVmIp() + "/32");
+ }
+
if (vspNic != null) {
vspStaticNatBuilder.nic(vspNic);
}
@@ -403,11 +437,24 @@ public VspStaticNat buildVspStaticNat(Boolean forRevoke, IPAddressVO staticNatIp
}
public VspStaticNat buildVspStaticNat(Boolean forRevoke, IPAddressVO staticNatIp, VlanVO staticNatVlan, NicVO nic) {
- VspNic vspNic = (nic != null) ?buildVspNic(nic) : null;
+ NicSecondaryIpVO nicSecondaryIp = null;
+
+ if (nic == null && staticNatIp.getAssociatedWithVmId() != null && staticNatIp.getVmIp() != null) {
+ nicSecondaryIp = _nicSecondaryIpDao.findByIp4AddressAndInstanceId(staticNatIp.getAssociatedWithVmId(), staticNatIp.getVmIp());
+ if (nicSecondaryIp != null) {
+ nic = _nicDao.findById(nicSecondaryIp.getNicId());
+ }
+ }
+
+ VspNic vspNic = (nic != null) ? buildVspNic(nic, nicSecondaryIp) : null;
return buildVspStaticNat(forRevoke, staticNatIp, staticNatVlan, vspNic);
}
public VspAclRule buildVspAclRule(FirewallRule firewallRule, Network network) {
+ return buildVspAclRule(firewallRule, network, null);
+ }
+
+ public VspAclRule buildVspAclRule(FirewallRule firewallRule, Network network, IPAddressVO staticNat) {
VspAclRule.Builder vspAclRuleBuilder = new VspAclRule.Builder()
.uuid(firewallRule.getUuid())
.protocol(firewallRule.getProtocol())
@@ -415,35 +462,25 @@ public VspAclRule buildVspAclRule(FirewallRule firewallRule, Network network) {
.endPort(firewallRule.getSourcePortEnd())
.sourceCidrList(firewallRule.getSourceCidrList())
.priority(-1)
- .type(VspAclRule.ACLType.Firewall);
-
- switch (firewallRule.getState()) {
- case Active:
- vspAclRuleBuilder.state(VspAclRule.ACLState.Active); break;
- case Add:
- vspAclRuleBuilder.state(VspAclRule.ACLState.Add); break;
- case Revoke:
- vspAclRuleBuilder.state(VspAclRule.ACLState.Revoke);
- }
-
- switch (firewallRule.getTrafficType()) {
- case Ingress:
- vspAclRuleBuilder.trafficType(VspAclRule.ACLTrafficType.Ingress); break;
- case Egress:
- vspAclRuleBuilder.trafficType(VspAclRule.ACLTrafficType.Egress);
- }
+ .type(VspAclRule.ACLType.Firewall)
+ .state(getEnumValue(firewallRule.getState(), VspAclRule.ACLState.class))
+ .trafficType(getEnumValue(firewallRule.getTrafficType(), VspAclRule.ACLTrafficType.class));
NetworkOfferingVO networkOffering = _networkOfferingDao.findById(network.getNetworkOfferingId());
if (firewallRule.getTrafficType() == FirewallRule.TrafficType.Egress && networkOffering.getEgressDefaultPolicy()) {
- vspAclRuleBuilder.action(VspAclRule.ACLAction.Deny);
+ vspAclRuleBuilder.deny();
} else {
- vspAclRuleBuilder.action(VspAclRule.ACLAction.Allow);
+ vspAclRuleBuilder.allow();
}
- if (firewallRule.getSourceIpAddressId() != null) {
- IPAddressVO ipAddress = _ipAddressDao.findById(firewallRule.getSourceIpAddressId());
- if (ipAddress != null) {
- vspAclRuleBuilder.sourceIpAddress(ipAddress.getVmIp() + "/32");
+ if (staticNat == null && firewallRule.getSourceIpAddressId() != null) {
+ IPAddressVO staticNatIp = _ipAddressDao.findById(firewallRule.getSourceIpAddressId());
+
+ if (staticNatIp != null) {
+ VlanVO staticNatVlan = _vlanDao.findById(staticNatIp.getVlanId());
+ NicVO nic = _nicDao.findByIp4AddressAndNetworkId(staticNatIp.getVmIp(), staticNatIp.getAssociatedWithNetworkId());
+
+ vspAclRuleBuilder.staticNat(buildVspStaticNat(null, staticNatIp, staticNatVlan, nic));
}
}
@@ -451,7 +488,7 @@ public VspAclRule buildVspAclRule(FirewallRule firewallRule, Network network) {
}
public VspAclRule buildVspAclRule(NetworkACLItem networkAcl) {
- VspAclRule.Builder vspAclRuleBuilder = new VspAclRule.Builder()
+ return new VspAclRule.Builder()
.uuid(networkAcl.getUuid())
.protocol(networkAcl.getProtocol())
.startPort(networkAcl.getSourcePortStart())
@@ -459,32 +496,11 @@ public VspAclRule buildVspAclRule(NetworkACLItem networkAcl) {
.sourceIpAddress(null)
.sourceCidrList(networkAcl.getSourceCidrList())
.priority(networkAcl.getNumber())
- .type(VspAclRule.ACLType.NetworkACL);
-
- switch (networkAcl.getState()) {
- case Active:
- vspAclRuleBuilder.state(VspAclRule.ACLState.Active); break;
- case Add:
- vspAclRuleBuilder.state(VspAclRule.ACLState.Add); break;
- case Revoke:
- vspAclRuleBuilder.state(VspAclRule.ACLState.Revoke);
- }
-
- switch (networkAcl.getTrafficType()) {
- case Ingress:
- vspAclRuleBuilder.trafficType(VspAclRule.ACLTrafficType.Ingress); break;
- case Egress:
- vspAclRuleBuilder.trafficType(VspAclRule.ACLTrafficType.Egress);
- }
-
- switch (networkAcl.getAction()) {
- case Allow:
- vspAclRuleBuilder.action(VspAclRule.ACLAction.Allow); break;
- case Deny:
- vspAclRuleBuilder.action(VspAclRule.ACLAction.Deny);
- }
-
- return vspAclRuleBuilder.build();
+ .type(VspAclRule.ACLType.NetworkACL)
+ .state(getEnumValue(networkAcl.getState(), VspAclRule.ACLState.class))
+ .trafficType(getEnumValue(networkAcl.getTrafficType(), VspAclRule.ACLTrafficType.class))
+ .action(getEnumValue(networkAcl.getAction(), VspAclRule.ACLAction.class))
+ .build();
}
/** Build VspDhcpVMOption to put on the VM interface */
diff --git a/plugins/network-elements/nuage-vsp/test/com/cloud/NuageTest.java b/plugins/network-elements/nuage-vsp/test/com/cloud/NuageTest.java
index 14742657e86..643a66f8122 100644
--- a/plugins/network-elements/nuage-vsp/test/com/cloud/NuageTest.java
+++ b/plugins/network-elements/nuage-vsp/test/com/cloud/NuageTest.java
@@ -21,6 +21,7 @@
import java.util.ArrayList;
+import net.nuage.vsp.acs.client.api.model.NetworkRelatedVsdIds;
import net.nuage.vsp.acs.client.api.model.VspAclRule;
import net.nuage.vsp.acs.client.api.model.VspDhcpDomainOption;
import net.nuage.vsp.acs.client.api.model.VspDhcpVMOption;
@@ -113,6 +114,16 @@ protected VspNetwork buildVspNetwork() {
.cidr("networkCidr")
.gateway("networkGateway")
.virtualRouterIp("virtualRouterIp")
+ .networkRelatedVsdIds(buildNetworkRelatedIds())
+ .build();
+ }
+
+ protected NetworkRelatedVsdIds buildNetworkRelatedIds() {
+ return new NetworkRelatedVsdIds.Builder()
+ .vsdZoneId("vsdZoneId")
+ .vsdDomainId("vsdDomainId")
+ .vsdEnterpriseId("vsdEnterpriseId")
+ .vsdSubnetId("vsdSubnetId")
.build();
}
diff --git a/plugins/network-elements/nuage-vsp/test/com/cloud/network/element/NuageVspElementTest.java b/plugins/network-elements/nuage-vsp/test/com/cloud/network/element/NuageVspElementTest.java
index 1916271db69..3805b13e528 100644
--- a/plugins/network-elements/nuage-vsp/test/com/cloud/network/element/NuageVspElementTest.java
+++ b/plugins/network-elements/nuage-vsp/test/com/cloud/network/element/NuageVspElementTest.java
@@ -56,7 +56,6 @@
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.NuageVspDeviceVO;
-import com.cloud.network.PhysicalNetwork;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.IPAddressVO;
@@ -332,7 +331,7 @@ public void testShutdownVpc() throws Exception {
when(context.getAccount()).thenReturn(acc);
PhysicalNetworkVO physNet = mock(PhysicalNetworkVO.class);
- when(physNet.getIsolationMethods()).thenReturn(Lists.newArrayList(PhysicalNetwork.IsolationMethod.VSP.name()));
+ when(physNet.getIsolationMethods()).thenReturn(Lists.newArrayList("VSP"));
when(physNet.getId()).thenReturn(NETWORK_ID);
when(_physicalNetworkDao.listByZone(NETWORK_ID)).thenReturn(Lists.newArrayList(physNet));
diff --git a/plugins/network-elements/nuage-vsp/test/com/cloud/network/guru/NuageVspGuestNetworkGuruTest.java b/plugins/network-elements/nuage-vsp/test/com/cloud/network/guru/NuageVspGuestNetworkGuruTest.java
index 8f334eba784..e92f4a7b9e2 100644
--- a/plugins/network-elements/nuage-vsp/test/com/cloud/network/guru/NuageVspGuestNetworkGuruTest.java
+++ b/plugins/network-elements/nuage-vsp/test/com/cloud/network/guru/NuageVspGuestNetworkGuruTest.java
@@ -25,6 +25,7 @@
import java.util.Arrays;
import java.util.Collections;
+import net.nuage.vsp.acs.client.api.model.NetworkRelatedVsdIds;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
@@ -37,6 +38,8 @@
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
+import com.cloud.agent.api.guru.ImplementNetworkVspCommand;
+import com.cloud.agent.api.manager.ImplementNetworkVspAnswer;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenter.NetworkType;
@@ -142,6 +145,7 @@ public void setUp() throws Exception {
when(_hostDao.findById(NETWORK_ID)).thenReturn(host);
when(host.getId()).thenReturn(NETWORK_ID);
when(_agentManager.easySend(eq(NETWORK_ID), any(Command.class))).thenReturn(new Answer(null));
+ when(_agentManager.easySend(eq(NETWORK_ID), any(ImplementNetworkVspCommand.class))).thenReturn(new ImplementNetworkVspAnswer(null, new NetworkRelatedVsdIds.Builder().build()));
when(_nuageVspManager.getNuageVspHost(NETWORK_ID)).thenReturn(host);
final NuageVspDeviceVO device = mock(NuageVspDeviceVO.class);
diff --git a/plugins/network-elements/nuage-vsp/test/com/cloud/network/resource/NuageVspResourceTest.java b/plugins/network-elements/nuage-vsp/test/com/cloud/network/resource/NuageVspResourceTest.java
index e497ec4d396..fb67e6ff9d7 100644
--- a/plugins/network-elements/nuage-vsp/test/com/cloud/network/resource/NuageVspResourceTest.java
+++ b/plugins/network-elements/nuage-vsp/test/com/cloud/network/resource/NuageVspResourceTest.java
@@ -58,6 +58,7 @@
import com.cloud.agent.api.guru.ImplementNetworkVspCommand;
import com.cloud.agent.api.guru.ReserveVmInterfaceVspCommand;
import com.cloud.agent.api.guru.TrashNetworkVspCommand;
+import com.cloud.agent.api.manager.ImplementNetworkVspAnswer;
import com.cloud.host.Host;
import static org.junit.Assert.assertEquals;
@@ -152,7 +153,7 @@ public void testImplementNetworkVspCommand() throws Exception {
VspNetwork vspNetwork = buildVspNetwork();
VspDhcpDomainOption vspDhcpOptions = buildspDhcpDomainOption();
ImplementNetworkVspCommand cmd = new ImplementNetworkVspCommand(vspNetwork, vspDhcpOptions);
- com.cloud.agent.api.Answer implNtwkAns = _resource.executeRequest(cmd);
+ ImplementNetworkVspAnswer implNtwkAns = (ImplementNetworkVspAnswer)_resource.executeRequest(cmd);
assertTrue(implNtwkAns.getResult());
verify(_mockNuageVspGuruClient).implement(vspNetwork, vspDhcpOptions);
}
diff --git a/plugins/network-elements/nuage-vsp/test/com/cloud/util/NuageVspEntityBuilderTest.java b/plugins/network-elements/nuage-vsp/test/com/cloud/util/NuageVspEntityBuilderTest.java
index 7ebdeb371a3..0ac13becaac 100644
--- a/plugins/network-elements/nuage-vsp/test/com/cloud/util/NuageVspEntityBuilderTest.java
+++ b/plugins/network-elements/nuage-vsp/test/com/cloud/util/NuageVspEntityBuilderTest.java
@@ -19,17 +19,20 @@
package com.cloud.util;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import net.nuage.vsp.acs.client.api.model.Protocol;
+import net.nuage.vsp.acs.client.api.model.VspAclRule;
+import net.nuage.vsp.acs.client.api.model.VspDomain;
+import net.nuage.vsp.acs.client.api.model.VspNetwork;
+import net.nuage.vsp.acs.client.api.model.VspNic;
+import net.nuage.vsp.acs.client.api.model.VspStaticNat;
+import net.nuage.vsp.acs.client.api.model.VspVm;
+import org.apache.cloudstack.resourcedetail.dao.VpcDetailsDao;
import org.junit.Before;
import org.junit.Test;
+import com.google.common.collect.Lists;
+
import com.cloud.NuageTest;
import com.cloud.dc.VlanDetailsVO;
import com.cloud.dc.VlanVO;
@@ -57,15 +60,15 @@
import com.cloud.vm.NicProfile;
import com.cloud.vm.NicVO;
import com.cloud.vm.VirtualMachine;
-import com.google.common.collect.Lists;
+import com.cloud.vm.dao.NicDao;
-import net.nuage.vsp.acs.client.api.model.Protocol;
-import net.nuage.vsp.acs.client.api.model.VspAclRule;
-import net.nuage.vsp.acs.client.api.model.VspDomain;
-import net.nuage.vsp.acs.client.api.model.VspNetwork;
-import net.nuage.vsp.acs.client.api.model.VspNic;
-import net.nuage.vsp.acs.client.api.model.VspStaticNat;
-import net.nuage.vsp.acs.client.api.model.VspVm;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class NuageVspEntityBuilderTest extends NuageTest {
@@ -76,8 +79,12 @@
private static final long L2_NETWORK_OFFERING_ID = 3L;
private static final long VPC_ID = 1L;
private static final long SOURCE_IP_ADDRESS_ID = 1L;
+ private static final long VM_ID = 4L;
+ private static final long VLAN_ID = 5L;
+ public static final String VM_IP = "192.168.0.24";
private VpcDao _vpcDao = mock(VpcDao.class);
+ private VpcDetailsDao _vpcDetailsDao = mock(VpcDetailsDao.class);
private DomainDao _domainDao = mock(DomainDao.class);
private AccountDao _accountDao = mock(AccountDao.class);
private NetworkDao _networkDao = mock(NetworkDao.class);
@@ -87,6 +94,7 @@
private VlanDetailsDao _vlanDetailsDao = mock(VlanDetailsDao.class);
private IPAddressDao _ipAddressDao = mock(IPAddressDao.class);
private NetworkDetailsDao _networkDetailsDao = mock(NetworkDetailsDao.class);
+ private NicDao _nicDao = mock(NicDao.class);
private NuageVspEntityBuilder _nuageVspEntityBuilder = new NuageVspEntityBuilder();
private DomainVO _mockedDomain = mock(DomainVO.class);
@@ -115,6 +123,7 @@ public void setUp() throws Exception {
super.setUp();
_nuageVspEntityBuilder._vpcDao = _vpcDao;
+ _nuageVspEntityBuilder._vpcDetailsDao = _vpcDetailsDao;
_nuageVspEntityBuilder._domainDao = _domainDao;
_nuageVspEntityBuilder._accountDao = _accountDao;
_nuageVspEntityBuilder._networkDao = _networkDao;
@@ -126,6 +135,7 @@ public void setUp() throws Exception {
_nuageVspEntityBuilder._ipAddressDao = _ipAddressDao;
_nuageVspEntityBuilder._networkModel = _networkModel;
_nuageVspEntityBuilder._networkDetailsDao = _networkDetailsDao;
+ _nuageVspEntityBuilder._nicDao = _nicDao;
setUpMockedDomain();
setUpMockedAccount();
@@ -208,12 +218,15 @@ public void testBuildVspStaticNat() {
}
@Test
- public void testBuildVspAclRule() {
+ public void testBuildVspAclRuleAcl() {
+ VspAclRule vspAclRule = _nuageVspEntityBuilder.buildVspAclRule(_mockedNetworkAclItem);
+ validateVspAclRule(vspAclRule, false);
+ }
+
+ @Test
+ public void testBuildVspAclRuleFirewall() {
VspAclRule vspAclRule = _nuageVspEntityBuilder.buildVspAclRule(_mockedFirewallRule, _mockedNetwork);
validateVspAclRule(vspAclRule, true);
-
- vspAclRule = _nuageVspEntityBuilder.buildVspAclRule(_mockedNetworkAclItem);
- validateVspAclRule(vspAclRule, false);
}
private void validateVspDomain(VspDomain vspDomain) {
@@ -229,6 +242,7 @@ private void validateVspNetwork(VspNetwork vspNetwork, boolean isL2, boolean isL
assertEquals("networkName", vspNetwork.getName());
assertNotNull(vspNetwork.getVspDomain());
validateVspDomain(vspNetwork.getVspDomain());
+
assertEquals("accountName", vspNetwork.getAccountName());
assertEquals("accountUuid", vspNetwork.getAccountUuid());
@@ -262,13 +276,14 @@ private void validateVspNic(VspNic vspNic) {
assertEquals("nicUuid", vspNic.getUuid());
assertEquals("macAddress", vspNic.getMacAddress());
assertEquals(true, vspNic.getUseStaticIp());
- assertEquals("10.10.10.2", vspNic.getIp());
+ assertEquals("192.168.0.24", vspNic.getIp());
}
private void validateVspStaticNat(VspStaticNat vspStaticNat, Boolean forRevoke) {
assertEquals("staticNatIpUuid", vspStaticNat.getIpUuid());
assertEquals("10.10.10.2", vspStaticNat.getIpAddress());
assertEquals(forRevoke, vspStaticNat.getRevoke());
+ assertEquals(VspStaticNat.State.Allocated, vspStaticNat.getState());
assertEquals(true, vspStaticNat.getOneToOneNat());
assertEquals("staticNatVlanUuid", vspStaticNat.getVlanUuid());
assertEquals("10.10.10.1", vspStaticNat.getVlanGateway());
@@ -286,10 +301,13 @@ private void validateVspAclRule(VspAclRule vspAclRule, boolean isFirewall) {
if (isFirewall) {
assertEquals(VspAclRule.ACLType.Firewall, vspAclRule.getType());
- assertEquals("192.168.0.24/32", vspAclRule.getSourceIpAddress());
+ final VspStaticNat staticNat = vspAclRule.getStaticNat();
+ assertNotNull(staticNat);
+ assertEquals("192.168.0.24/32", staticNat.getDestinationIp());
assertEquals(VspAclRule.ACLAction.Deny, vspAclRule.getAction());
} else {
assertEquals(VspAclRule.ACLType.NetworkACL, vspAclRule.getType());
+ assertNull(vspAclRule.getStaticNat());
assertNull(vspAclRule.getSourceIpAddress());
assertEquals(VspAclRule.ACLAction.Allow, vspAclRule.getAction());
}
@@ -345,14 +363,14 @@ private void setUpMockedVirtualMachine(VirtualMachine virtualMachineToMock, bool
private void setUpMockedNicProfile() {
when(_mockedNicProfile.getMacAddress()).thenReturn("macAddress");
- when(_mockedNicProfile.getIPv4Address()).thenReturn("10.10.10.2");
+ when(_mockedNicProfile.getIPv4Address()).thenReturn(VM_IP);
when(_mockedNicProfile.getNetworkId()).thenReturn(NETWORK_ID);
}
private void setUpMockedNic() {
when(_mockedNic.getUuid()).thenReturn("nicUuid");
when(_mockedNic.getMacAddress()).thenReturn("macAddress");
- when(_mockedNic.getIPv4Address()).thenReturn("10.10.10.2");
+ when(_mockedNic.getIPv4Address()).thenReturn(VM_IP);
when(_mockedNic.getNetworkId()).thenReturn(NETWORK_ID);
}
@@ -360,8 +378,11 @@ private void setUpMockedStaticNatIp() {
when(_mockedStaticNatIp.getUuid()).thenReturn("staticNatIpUuid");
when(_mockedStaticNatIp.getAddress()).thenReturn(new Ip("10.10.10.2"));
when(_mockedStaticNatIp.isOneToOneNat()).thenReturn(true);
- when(_mockedStaticNatIp.getVmIp()).thenReturn("192.168.0.24");
+ when(_mockedStaticNatIp.getVmIp()).thenReturn(VM_IP);
+ when(_mockedStaticNatIp.getAssociatedWithNetworkId()).thenReturn(NETWORK_ID);
+ when(_mockedStaticNatIp.getAssociatedWithVmId()).thenReturn(VM_ID);
when(_mockedStaticNatIp.getState()).thenReturn(IpAddress.State.Allocated);
+ when(_mockedStaticNatIp.getVlanId()).thenReturn(VLAN_ID);
}
private void setUpMockedStaticNatVlan() {
@@ -410,8 +431,11 @@ private void setUpMockedDaoCalls() {
when(_networkModel.areServicesSupportedByNetworkOffering(SHARED_NETWORK_OFFERING_ID, Network.Service.Firewall)).thenReturn(true);
when(_networkModel.areServicesSupportedByNetworkOffering(L2_NETWORK_OFFERING_ID, Network.Service.Firewall)).thenReturn(true);
when(_vlanDao.listVlansByNetworkId(NETWORK_ID)).thenReturn(Lists.newArrayList(_mockedVlan));
+ when(_vlanDao.findById(VLAN_ID)).thenReturn(_mockedVlan);
when(_vlanDetailsDao.findDetail(anyLong(), anyString())).thenReturn(_mockedVlanDetail);
when(_vpcDao.findById(VPC_ID)).thenReturn(_mockedVpc);
when(_ipAddressDao.findById(SOURCE_IP_ADDRESS_ID)).thenReturn(_mockedStaticNatIp);
+ when(_vpcDetailsDao.listDetailsKeyPairs(VPC_ID)).thenReturn(null);
+ when(_nicDao.findByIp4AddressAndNetworkId("192.168.0.24", NETWORK_ID)).thenReturn(_mockedNic);
}
}
diff --git a/plugins/network-elements/opendaylight/pom.xml b/plugins/network-elements/opendaylight/pom.xml
index 5bf8f182b44..ad425b0a62f 100644
--- a/plugins/network-elements/opendaylight/pom.xml
+++ b/plugins/network-elements/opendaylight/pom.xml
@@ -25,7 +25,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/OpendaylightGuestNetworkGuru.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/OpendaylightGuestNetworkGuru.java
index cbaa4d024b3..4e2bf892dd2 100644
--- a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/OpendaylightGuestNetworkGuru.java
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/OpendaylightGuestNetworkGuru.java
@@ -19,26 +19,6 @@
package org.apache.cloudstack.network.opendaylight;
-import java.util.List;
-import java.util.UUID;
-
-import javax.inject.Inject;
-
-import org.apache.log4j.Logger;
-
-import org.apache.cloudstack.network.opendaylight.agent.commands.AddHypervisorCommand;
-import org.apache.cloudstack.network.opendaylight.agent.commands.ConfigureNetworkCommand;
-import org.apache.cloudstack.network.opendaylight.agent.commands.ConfigurePortCommand;
-import org.apache.cloudstack.network.opendaylight.agent.commands.DestroyNetworkCommand;
-import org.apache.cloudstack.network.opendaylight.agent.commands.DestroyPortCommand;
-import org.apache.cloudstack.network.opendaylight.agent.responses.AddHypervisorAnswer;
-import org.apache.cloudstack.network.opendaylight.agent.responses.ConfigureNetworkAnswer;
-import org.apache.cloudstack.network.opendaylight.agent.responses.ConfigurePortAnswer;
-import org.apache.cloudstack.network.opendaylight.agent.responses.DestroyNetworkAnswer;
-import org.apache.cloudstack.network.opendaylight.agent.responses.DestroyPortAnswer;
-import org.apache.cloudstack.network.opendaylight.dao.OpenDaylightControllerMappingDao;
-import org.apache.cloudstack.network.opendaylight.dao.OpenDaylightControllerVO;
-
import com.cloud.agent.AgentManager;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenter.NetworkType;
@@ -68,6 +48,23 @@
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachineProfile;
+import org.apache.cloudstack.network.opendaylight.agent.commands.AddHypervisorCommand;
+import org.apache.cloudstack.network.opendaylight.agent.commands.ConfigureNetworkCommand;
+import org.apache.cloudstack.network.opendaylight.agent.commands.ConfigurePortCommand;
+import org.apache.cloudstack.network.opendaylight.agent.commands.DestroyNetworkCommand;
+import org.apache.cloudstack.network.opendaylight.agent.commands.DestroyPortCommand;
+import org.apache.cloudstack.network.opendaylight.agent.responses.AddHypervisorAnswer;
+import org.apache.cloudstack.network.opendaylight.agent.responses.ConfigureNetworkAnswer;
+import org.apache.cloudstack.network.opendaylight.agent.responses.ConfigurePortAnswer;
+import org.apache.cloudstack.network.opendaylight.agent.responses.DestroyNetworkAnswer;
+import org.apache.cloudstack.network.opendaylight.agent.responses.DestroyPortAnswer;
+import org.apache.cloudstack.network.opendaylight.dao.OpenDaylightControllerMappingDao;
+import org.apache.cloudstack.network.opendaylight.dao.OpenDaylightControllerVO;
+import org.apache.log4j.Logger;
+
+import javax.inject.Inject;
+import java.util.List;
+import java.util.UUID;
public class OpendaylightGuestNetworkGuru extends GuestNetworkGuru {
private static final Logger s_logger = Logger.getLogger(OpendaylightGuestNetworkGuru.class);
@@ -86,7 +83,7 @@
NetworkDao networkDao;
public OpendaylightGuestNetworkGuru() {
- _isolationMethods = new IsolationMethod[] {IsolationMethod.ODL};
+ _isolationMethods = new IsolationMethod[] {new IsolationMethod("ODL")};
}
@Override
diff --git a/plugins/network-elements/ovs/pom.xml b/plugins/network-elements/ovs/pom.xml
index a9d4c9d5190..365f751490d 100644
--- a/plugins/network-elements/ovs/pom.xml
+++ b/plugins/network-elements/ovs/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
</project>
diff --git a/plugins/network-elements/ovs/src/com/cloud/network/guru/OvsGuestNetworkGuru.java b/plugins/network-elements/ovs/src/com/cloud/network/guru/OvsGuestNetworkGuru.java
index f3f8ea052bd..50b98579aef 100644
--- a/plugins/network-elements/ovs/src/com/cloud/network/guru/OvsGuestNetworkGuru.java
+++ b/plugins/network-elements/ovs/src/com/cloud/network/guru/OvsGuestNetworkGuru.java
@@ -16,14 +16,6 @@
// under the License.
package com.cloud.network.guru;
-import com.cloud.network.vpc.VpcVO;
-import com.cloud.network.vpc.dao.VpcDao;
-import javax.inject.Inject;
-
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
-
-import org.apache.cloudstack.context.CallContext;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenter.NetworkType;
@@ -45,12 +37,19 @@
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.dao.PhysicalNetworkVO;
import com.cloud.network.ovs.OvsTunnelManager;
+import com.cloud.network.vpc.VpcVO;
+import com.cloud.network.vpc.dao.VpcDao;
import com.cloud.offering.NetworkOffering;
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
import com.cloud.user.Account;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachineProfile;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import javax.inject.Inject;
@Component
public class OvsGuestNetworkGuru extends GuestNetworkGuru {
@@ -66,8 +65,8 @@
OvsGuestNetworkGuru() {
super();
- _isolationMethods = new IsolationMethod[] {IsolationMethod.GRE,
- IsolationMethod.L3, IsolationMethod.VLAN};
+ _isolationMethods = new IsolationMethod[] {new IsolationMethod("GRE"),
+ new IsolationMethod("L3"), new IsolationMethod("VLAN")};
}
@Override
diff --git a/plugins/network-elements/palo-alto/pom.xml b/plugins/network-elements/palo-alto/pom.xml
index 7b63eb2e93a..101f24b6cbe 100644
--- a/plugins/network-elements/palo-alto/pom.xml
+++ b/plugins/network-elements/palo-alto/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
</project>
diff --git a/plugins/network-elements/stratosphere-ssp/pom.xml b/plugins/network-elements/stratosphere-ssp/pom.xml
index 00f1c6345be..e2865316764 100644
--- a/plugins/network-elements/stratosphere-ssp/pom.xml
+++ b/plugins/network-elements/stratosphere-ssp/pom.xml
@@ -25,7 +25,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
</project>
diff --git a/plugins/network-elements/stratosphere-ssp/src/org/apache/cloudstack/network/guru/SspGuestNetworkGuru.java b/plugins/network-elements/stratosphere-ssp/src/org/apache/cloudstack/network/guru/SspGuestNetworkGuru.java
index be73e14060f..9ede8cc5a3e 100644
--- a/plugins/network-elements/stratosphere-ssp/src/org/apache/cloudstack/network/guru/SspGuestNetworkGuru.java
+++ b/plugins/network-elements/stratosphere-ssp/src/org/apache/cloudstack/network/guru/SspGuestNetworkGuru.java
@@ -16,13 +16,6 @@
// under the License.
package org.apache.cloudstack.network.guru;
-import javax.inject.Inject;
-
-import org.apache.log4j.Logger;
-
-import org.apache.cloudstack.network.element.SspElement;
-import org.apache.cloudstack.network.element.SspManager;
-
import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.InsufficientAddressCapacityException;
@@ -40,6 +33,11 @@
import com.cloud.vm.ReservationContext;
import com.cloud.vm.ReservationContextImpl;
import com.cloud.vm.VirtualMachineProfile;
+import org.apache.cloudstack.network.element.SspElement;
+import org.apache.cloudstack.network.element.SspManager;
+import org.apache.log4j.Logger;
+
+import javax.inject.Inject;
/**
* Stratosphere SDN Platform NetworkGuru
@@ -56,7 +54,7 @@
public SspGuestNetworkGuru() {
super();
- _isolationMethods = new IsolationMethod[] {IsolationMethod.SSP};
+ _isolationMethods = new IsolationMethod[] {new IsolationMethod("SSP")};
}
@Override
diff --git a/plugins/network-elements/vxlan/pom.xml b/plugins/network-elements/vxlan/pom.xml
index bfee46a9dda..3f890f9392e 100644
--- a/plugins/network-elements/vxlan/pom.xml
+++ b/plugins/network-elements/vxlan/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
</project>
diff --git a/plugins/network-elements/vxlan/src/com/cloud/network/guru/VxlanGuestNetworkGuru.java b/plugins/network-elements/vxlan/src/com/cloud/network/guru/VxlanGuestNetworkGuru.java
index 8d2015584da..c065bd191d0 100644
--- a/plugins/network-elements/vxlan/src/com/cloud/network/guru/VxlanGuestNetworkGuru.java
+++ b/plugins/network-elements/vxlan/src/com/cloud/network/guru/VxlanGuestNetworkGuru.java
@@ -17,11 +17,6 @@
package com.cloud.network.guru;
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
-
-import org.apache.cloudstack.context.CallContext;
-
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.deploy.DeployDestination;
@@ -44,6 +39,9 @@
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachineProfile;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
@Component
public class VxlanGuestNetworkGuru extends GuestNetworkGuru {
@@ -51,7 +49,7 @@
public VxlanGuestNetworkGuru() {
super();
- _isolationMethods = new IsolationMethod[] {IsolationMethod.VXLAN};
+ _isolationMethods = new IsolationMethod[] {new IsolationMethod("VXLAN")};
}
@Override
diff --git a/plugins/outofbandmanagement-drivers/ipmitool/pom.xml b/plugins/outofbandmanagement-drivers/ipmitool/pom.xml
index 832457a0c9e..649bc9a4fbb 100644
--- a/plugins/outofbandmanagement-drivers/ipmitool/pom.xml
+++ b/plugins/outofbandmanagement-drivers/ipmitool/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/outofbandmanagement-drivers/nested-cloudstack/pom.xml b/plugins/outofbandmanagement-drivers/nested-cloudstack/pom.xml
new file mode 100644
index 00000000000..29ae8883155
--- /dev/null
+++ b/plugins/outofbandmanagement-drivers/nested-cloudstack/pom.xml
@@ -0,0 +1,46 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>cloud-plugin-outofbandmanagement-driver-nested-cloudstack</artifactId>
+ <name>Apache CloudStack Plugin - Power Management Driver nested-cloudstack</name>
+ <parent>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloudstack-plugins</artifactId>
+ <version>4.11.0.0-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-utils</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>br.com.autonomiccs</groupId>
+ <artifactId>apache-cloudstack-java-client</artifactId>
+ <version>1.0.6</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/plugins/outofbandmanagement-drivers/nested-cloudstack/resources/META-INF/cloudstack/nested-cloudstack/module.properties b/plugins/outofbandmanagement-drivers/nested-cloudstack/resources/META-INF/cloudstack/nested-cloudstack/module.properties
new file mode 100644
index 00000000000..c992ed13b64
--- /dev/null
+++ b/plugins/outofbandmanagement-drivers/nested-cloudstack/resources/META-INF/cloudstack/nested-cloudstack/module.properties
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+name=nested-cloudstack
+parent=outofbandmanagement
diff --git a/plugins/outofbandmanagement-drivers/nested-cloudstack/resources/META-INF/cloudstack/nested-cloudstack/spring-nested-cloudstack-context.xml b/plugins/outofbandmanagement-drivers/nested-cloudstack/resources/META-INF/cloudstack/nested-cloudstack/spring-nested-cloudstack-context.xml
new file mode 100644
index 00000000000..252a95ce829
--- /dev/null
+++ b/plugins/outofbandmanagement-drivers/nested-cloudstack/resources/META-INF/cloudstack/nested-cloudstack/spring-nested-cloudstack-context.xml
@@ -0,0 +1,29 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
+>
+
+ <bean id="nestedCloudStackOutOfBandManagementDriver" class="org.apache.cloudstack.outofbandmanagement.driver.nestedcloudstack.NestedCloudStackOutOfBandManagementDriver">
+ <property name="name" value="NESTEDCLOUDSTACK" />
+ </bean>
+
+</beans>
diff --git a/plugins/outofbandmanagement-drivers/nested-cloudstack/src/org/apache/cloudstack/outofbandmanagement/driver/nestedcloudstack/NestedCloudStackOutOfBandManagementDriver.java b/plugins/outofbandmanagement-drivers/nested-cloudstack/src/org/apache/cloudstack/outofbandmanagement/driver/nestedcloudstack/NestedCloudStackOutOfBandManagementDriver.java
new file mode 100644
index 00000000000..37d5c577590
--- /dev/null
+++ b/plugins/outofbandmanagement-drivers/nested-cloudstack/src/org/apache/cloudstack/outofbandmanagement/driver/nestedcloudstack/NestedCloudStackOutOfBandManagementDriver.java
@@ -0,0 +1,147 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.outofbandmanagement.driver.nestedcloudstack;
+
+import br.com.autonomiccs.apacheCloudStack.client.ApacheCloudStackClient;
+import br.com.autonomiccs.apacheCloudStack.client.ApacheCloudStackRequest;
+import br.com.autonomiccs.apacheCloudStack.client.beans.ApacheCloudStackUser;
+import br.com.autonomiccs.apacheCloudStack.exceptions.ApacheCloudStackClientRequestRuntimeException;
+import com.cloud.utils.component.AdapterBase;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableMap;
+import org.apache.cloudstack.outofbandmanagement.OutOfBandManagement;
+import org.apache.cloudstack.outofbandmanagement.OutOfBandManagementDriver;
+import org.apache.cloudstack.outofbandmanagement.driver.OutOfBandManagementDriverChangePasswordCommand;
+import org.apache.cloudstack.outofbandmanagement.driver.OutOfBandManagementDriverCommand;
+import org.apache.cloudstack.outofbandmanagement.driver.OutOfBandManagementDriverPowerCommand;
+import org.apache.cloudstack.outofbandmanagement.driver.OutOfBandManagementDriverResponse;
+import org.apache.log4j.Logger;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+public final class NestedCloudStackOutOfBandManagementDriver extends AdapterBase implements OutOfBandManagementDriver {
+ private static final Logger LOG = Logger.getLogger(NestedCloudStackOutOfBandManagementDriver.class);
+
+ public OutOfBandManagementDriverResponse execute(final OutOfBandManagementDriverCommand cmd) {
+ OutOfBandManagementDriverResponse response = new OutOfBandManagementDriverResponse(null, "Unsupported Command", false);
+
+ if (cmd instanceof OutOfBandManagementDriverPowerCommand) {
+ response = execute((OutOfBandManagementDriverPowerCommand) cmd);
+ } else if (cmd instanceof OutOfBandManagementDriverChangePasswordCommand) {
+ throw new CloudRuntimeException("Change password operation is not supported by the nested-cloudstack out-of-band management driver");
+ }
+
+ return response;
+ }
+
+ protected void ensureOptionExists(final ImmutableMap<OutOfBandManagement.Option, String> options, final OutOfBandManagement.Option option) {
+ if (options != null && option != null && options.containsKey(option) && !Strings.isNullOrEmpty(options.get(option))) {
+ return;
+ }
+ throw new CloudRuntimeException("Invalid out-of-band management configuration detected for the nested-cloudstack driver");
+ }
+
+ protected OutOfBandManagement.PowerState getNestedVMPowerState(final String jsonResponse) {
+ if (Strings.isNullOrEmpty(jsonResponse)) {
+ return OutOfBandManagement.PowerState.Unknown;
+ }
+
+ final ObjectMapper mapper = new ObjectMapper();
+ try {
+ Map<String, Object> listResponse = mapper.readValue(jsonResponse, Map.class);
+ if (listResponse != null && listResponse.containsKey("listvirtualmachinesresponse")
+ && ((Map<String, Object>) listResponse.get("listvirtualmachinesresponse")).containsKey("virtualmachine")) {
+ Map<String, String> vmResponse = ((Map<String, List<Map<String, String>>>) listResponse.get("listvirtualmachinesresponse")).get("virtualmachine").get(0);
+ if (vmResponse != null && vmResponse.containsKey("state")) {
+ if("Running".equals(vmResponse.get("state"))) {
+ return OutOfBandManagement.PowerState.On;
+ } else if("Stopped".equals(vmResponse.get("state"))) {
+ return OutOfBandManagement.PowerState.Off;
+ }
+ }
+ }
+ } catch (IOException e) {
+ LOG.warn("Exception caught while de-serializing and reading state of the nested-cloudstack VM from the response: " + jsonResponse + ", with exception:", e);
+ }
+ return OutOfBandManagement.PowerState.Unknown;
+ }
+
+ private OutOfBandManagementDriverResponse execute(final OutOfBandManagementDriverPowerCommand cmd) {
+ if (cmd == null || cmd.getPowerOperation() == null) {
+ throw new CloudRuntimeException("Invalid out-of-band management power command provided to the nested-cloudstack driver");
+ }
+
+ final ImmutableMap<OutOfBandManagement.Option, String> options = cmd.getOptions();
+ ensureOptionExists(options, OutOfBandManagement.Option.ADDRESS);
+ ensureOptionExists(options, OutOfBandManagement.Option.PORT);
+ ensureOptionExists(options, OutOfBandManagement.Option.USERNAME);
+ ensureOptionExists(options, OutOfBandManagement.Option.PASSWORD);
+
+ final String url = options.get(OutOfBandManagement.Option.ADDRESS);
+ final String vmUuid = options.get(OutOfBandManagement.Option.PORT);
+ final String apiKey = options.get(OutOfBandManagement.Option.USERNAME);
+ final String secretKey = options.get(OutOfBandManagement.Option.PASSWORD);
+
+ final ApacheCloudStackUser apacheCloudStackUser = new ApacheCloudStackUser(secretKey, apiKey);
+ final ApacheCloudStackClient client = new ApacheCloudStackClient(url, apacheCloudStackUser);
+ client.setValidateServerHttpsCertificate(false);
+ client.setShouldRequestsExpire(false);
+ client.setConnectionTimeout((int) cmd.getTimeout().getStandardSeconds());
+
+ String apiName = "listVirtualMachines";
+ switch (cmd.getPowerOperation()) {
+ case ON:
+ apiName = "startVirtualMachine";
+ break;
+ case OFF:
+ case SOFT:
+ apiName = "stopVirtualMachine";
+ break;
+ case CYCLE:
+ case RESET:
+ apiName = "rebootVirtualMachine";
+ break;
+ }
+
+ final ApacheCloudStackRequest apacheCloudStackRequest = new ApacheCloudStackRequest(apiName);
+ apacheCloudStackRequest.addParameter("response", "json");
+ apacheCloudStackRequest.addParameter("forced", "true");
+ apacheCloudStackRequest.addParameter("id", vmUuid);
+
+ final String apiResponse;
+ try {
+ apiResponse = client.executeRequest(apacheCloudStackRequest);
+ } catch (final ApacheCloudStackClientRequestRuntimeException e) {
+ LOG.error("Nested CloudStack oobm plugin failed due to API error: ", e);
+ final OutOfBandManagementDriverResponse failedResponse = new OutOfBandManagementDriverResponse(e.getResponse(), "HTTP error code: " + e.getStatusCode(), false);
+ if (e.getStatusCode() == 401) {
+ failedResponse.setAuthFailure(true);
+ }
+ return failedResponse;
+ }
+
+ final OutOfBandManagementDriverResponse response = new OutOfBandManagementDriverResponse(apiResponse, null, true);
+ if (OutOfBandManagement.PowerOperation.STATUS.equals(cmd.getPowerOperation())) {
+ response.setPowerState(getNestedVMPowerState(apiResponse));
+ }
+ return response;
+ }
+}
diff --git a/plugins/outofbandmanagement-drivers/nested-cloudstack/test/org/apache/cloudstack/outofbandmanagement/driver/nestedcloudstack/NestedCloudStackOutOfBandManagementDriverTest.java b/plugins/outofbandmanagement-drivers/nested-cloudstack/test/org/apache/cloudstack/outofbandmanagement/driver/nestedcloudstack/NestedCloudStackOutOfBandManagementDriverTest.java
new file mode 100644
index 00000000000..5629773b9ef
--- /dev/null
+++ b/plugins/outofbandmanagement-drivers/nested-cloudstack/test/org/apache/cloudstack/outofbandmanagement/driver/nestedcloudstack/NestedCloudStackOutOfBandManagementDriverTest.java
@@ -0,0 +1,75 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.outofbandmanagement.driver.nestedcloudstack;
+
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.google.common.collect.ImmutableMap;
+import org.apache.cloudstack.outofbandmanagement.OutOfBandManagement;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import java.io.IOException;
+
+@RunWith(MockitoJUnitRunner.class)
+public class NestedCloudStackOutOfBandManagementDriverTest {
+ private NestedCloudStackOutOfBandManagementDriver driver = new NestedCloudStackOutOfBandManagementDriver();
+
+ @Test
+ public void testEnsureOptionExists() throws IOException {
+ final ImmutableMap.Builder<OutOfBandManagement.Option, String> builder = ImmutableMap.builder();
+ builder.put(OutOfBandManagement.Option.ADDRESS, "http://some.cloud/client/api");
+ final ImmutableMap<OutOfBandManagement.Option, String> options = builder.build();
+ driver.ensureOptionExists(options, OutOfBandManagement.Option.ADDRESS);
+
+ boolean caughtException = false;
+ try {
+ driver.ensureOptionExists(options, OutOfBandManagement.Option.PORT);
+ } catch (CloudRuntimeException e) {
+ caughtException = true;
+ }
+ Assert.assertTrue(caughtException);
+ }
+
+ @Test
+ public void testIsVMRunningTrue() throws IOException {
+ String json = "{\"listvirtualmachinesresponse\":{\"count\":1,\"virtualmachine\":[{\"id\":\"38fa7380-9543-486a-b083-190ecf726ba4\",\"name\":\"test-vm\",\"displayname\":\"test-vm\",\"account\":\"admin\",\"userid\":\"78ed9ce8-f3ee-11e4-91ab-00012e4fde1c\",\"username\":\"admin\",\"domainid\":\"53601d4b-f3ee-11e4-91ab-00012e4fde1c\",\"domain\":\"ROOT\",\"created\":\"2017-04-04T19:50:56+0200\",\"state\":\"Running\"}]}}";
+ Assert.assertEquals(driver.getNestedVMPowerState(json), OutOfBandManagement.PowerState.On);
+ }
+
+ @Test
+ public void testIsVMRunningFalse() throws IOException {
+ String json = "{\"listvirtualmachinesresponse\":{\"count\":1,\"virtualmachine\":[{\"id\":\"38fa7380-9543-486a-b083-190ecf726ba4\",\"name\":\"test-vm\",\"displayname\":\"test-vm\",\"account\":\"admin\",\"userid\":\"78ed9ce8-f3ee-11e4-91ab-00012e4fde1c\",\"username\":\"admin\",\"domainid\":\"53601d4b-f3ee-11e4-91ab-00012e4fde1c\",\"domain\":\"ROOT\",\"created\":\"2017-04-04T19:50:56+0200\",\"state\":\"Stopped\"}]}}";
+ Assert.assertEquals(driver.getNestedVMPowerState(json), OutOfBandManagement.PowerState.Off);
+ }
+
+ @Test
+ public void testIsVMRunningInvalidJson() throws IOException {
+ String json = "{\"listvirtualmachinesresponse\":{\"count\":1,\"virtualmachine\"83-190ecf726ba4\",\"name";
+ Assert.assertEquals(driver.getNestedVMPowerState(json), OutOfBandManagement.PowerState.Unknown);
+ }
+
+ @Test
+ public void testIsVMRunningEmptyJson() throws IOException {
+ String json = "{}";
+ Assert.assertEquals(driver.getNestedVMPowerState(json), OutOfBandManagement.PowerState.Unknown);
+ }
+}
diff --git a/plugins/pom.xml b/plugins/pom.xml
index b2176ec6280..f57fbdc126c 100755
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
</parent>
<build>
@@ -53,6 +53,7 @@
<module>acl/dynamic-role-based</module>
<module>affinity-group-processors/host-anti-affinity</module>
<module>affinity-group-processors/explicit-dedication</module>
+ <module>ca/root-ca</module>
<module>deployment-planners/user-concentrated-pod</module>
<module>deployment-planners/user-dispersing</module>
<module>deployment-planners/implicit-dedication</module>
@@ -82,6 +83,7 @@
<module>network-elements/stratosphere-ssp</module>
<module>network-elements/opendaylight</module>
<module>outofbandmanagement-drivers/ipmitool</module>
+ <module>outofbandmanagement-drivers/nested-cloudstack</module>
<module>storage-allocators/random</module>
<module>user-authenticators/ldap</module>
<module>user-authenticators/md5</module>
@@ -105,6 +107,8 @@
<module>network-elements/vxlan</module>
<module>network-elements/globodns</module>
<module>database/quota</module>
+ <module>integrations/cloudian</module>
+ <module>integrations/prometheus</module>
</modules>
<dependencies>
@@ -205,11 +209,5 @@
<module>hypervisors/simulator</module>
</modules>
</profile>
- <profile>
- <id>midonet</id>
- <modules>
- <module>network-elements/midonet</module>
- </modules>
- </profile>
</profiles>
</project>
diff --git a/plugins/storage-allocators/random/pom.xml b/plugins/storage-allocators/random/pom.xml
index e9a0ffe2bee..9a3b5e8b547 100644
--- a/plugins/storage-allocators/random/pom.xml
+++ b/plugins/storage-allocators/random/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/storage/image/default/pom.xml b/plugins/storage/image/default/pom.xml
index 49aa64d4716..076a9c45c2b 100644
--- a/plugins/storage/image/default/pom.xml
+++ b/plugins/storage/image/default/pom.xml
@@ -16,7 +16,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/storage/image/s3/pom.xml b/plugins/storage/image/s3/pom.xml
index 542cc4bf981..9a63fd27a03 100644
--- a/plugins/storage/image/s3/pom.xml
+++ b/plugins/storage/image/s3/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/storage/image/sample/pom.xml b/plugins/storage/image/sample/pom.xml
index c4bfab178db..dff7d38f632 100644
--- a/plugins/storage/image/sample/pom.xml
+++ b/plugins/storage/image/sample/pom.xml
@@ -16,7 +16,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/storage/image/swift/pom.xml b/plugins/storage/image/swift/pom.xml
index ad55fceee46..659e1304b15 100644
--- a/plugins/storage/image/swift/pom.xml
+++ b/plugins/storage/image/swift/pom.xml
@@ -16,7 +16,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/storage/volume/cloudbyte/pom.xml b/plugins/storage/volume/cloudbyte/pom.xml
index 6a453a2930c..fbbe9b151b7 100755
--- a/plugins/storage/volume/cloudbyte/pom.xml
+++ b/plugins/storage/volume/cloudbyte/pom.xml
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/lifecycle/ElastistorPrimaryDataStoreLifeCycle.java b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/lifecycle/ElastistorPrimaryDataStoreLifeCycle.java
index bbf35e68c24..d6a67b447c5 100644
--- a/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/lifecycle/ElastistorPrimaryDataStoreLifeCycle.java
+++ b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/lifecycle/ElastistorPrimaryDataStoreLifeCycle.java
@@ -359,7 +359,7 @@ public boolean attachCluster(DataStore store, ClusterScope scope) {
PrimaryDataStoreInfo primarystore = (PrimaryDataStoreInfo) store;
// Check if there is host up in this cluster
- List<HostVO> allHosts = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.Routing, primarystore.getClusterId(), primarystore.getPodId(), primarystore.getDataCenterId());
+ List<HostVO> allHosts = _resourceMgr.listAllUpHosts(Host.Type.Routing, primarystore.getClusterId(), primarystore.getPodId(), primarystore.getDataCenterId());
if (allHosts.isEmpty()) {
primaryDataStoreDao.expunge(primarystore.getId());
throw new CloudRuntimeException("No host up to associate a storage pool with in cluster " + primarystore.getClusterId());
diff --git a/plugins/storage/volume/default/pom.xml b/plugins/storage/volume/default/pom.xml
index 03ec6f9152e..cb872a6ec53 100644
--- a/plugins/storage/volume/default/pom.xml
+++ b/plugins/storage/volume/default/pom.xml
@@ -16,7 +16,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java
index ab9cecf8127..a500fdb6354 100644
--- a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java
+++ b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java
@@ -387,7 +387,7 @@ public boolean attachCluster(DataStore store, ClusterScope scope) {
PrimaryDataStoreInfo primarystore = (PrimaryDataStoreInfo)store;
// Check if there is host up in this cluster
List<HostVO> allHosts =
- _resourceMgr.listAllUpAndEnabledHosts(Host.Type.Routing, primarystore.getClusterId(), primarystore.getPodId(), primarystore.getDataCenterId());
+ _resourceMgr.listAllUpHosts(Host.Type.Routing, primarystore.getClusterId(), primarystore.getPodId(), primarystore.getDataCenterId());
if (allHosts.isEmpty()) {
primaryDataStoreDao.expunge(primarystore.getId());
throw new CloudRuntimeException("No host up to associate a storage pool with in cluster " + primarystore.getClusterId());
diff --git a/plugins/storage/volume/default/test/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImplTest.java b/plugins/storage/volume/default/test/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImplTest.java
new file mode 100644
index 00000000000..ffdc5143e8c
--- /dev/null
+++ b/plugins/storage/volume/default/test/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImplTest.java
@@ -0,0 +1,170 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.storage.datastore.lifecycle;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.ModifyStoragePoolAnswer;
+import com.cloud.agent.api.ModifyStoragePoolCommand;
+import com.cloud.agent.api.StoragePoolInfo;
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+import com.cloud.host.Status;
+import com.cloud.resource.ResourceManager;
+import com.cloud.resource.ResourceState;
+import com.cloud.storage.DataStoreRole;
+import com.cloud.storage.Storage;
+import com.cloud.storage.StorageManager;
+import com.cloud.storage.StorageManagerImpl;
+import com.cloud.storage.StoragePoolHostVO;
+import com.cloud.storage.dao.StoragePoolHostDao;
+import junit.framework.TestCase;
+import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager;
+import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener;
+import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
+import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle;
+import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
+import org.apache.cloudstack.storage.datastore.provider.DefaultHostListener;
+import org.apache.cloudstack.storage.volume.datastore.PrimaryDataStoreHelper;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * Created by ajna123 on 9/22/2015.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class CloudStackPrimaryDataStoreLifeCycleImplTest extends TestCase {
+
+ @InjectMocks
+ PrimaryDataStoreLifeCycle _cloudStackPrimaryDataStoreLifeCycle = new CloudStackPrimaryDataStoreLifeCycleImpl();
+
+ @Spy
+ @InjectMocks
+ StorageManager storageMgr = new StorageManagerImpl();
+
+ @Mock
+ ResourceManager _resourceMgr;
+
+ @Mock
+ AgentManager agentMgr;
+
+ @Mock
+ DataStoreManager _dataStoreMgr;
+
+ @Mock
+ DataStoreProviderManager _dataStoreProviderMgr;
+
+ @Spy
+ @InjectMocks
+ HypervisorHostListener hostListener = new DefaultHostListener();
+
+ @Mock
+ StoragePoolHostDao storagePoolHostDao;
+
+ @Mock
+ PrimaryDataStore store;
+
+ @Mock
+ DataStoreProvider dataStoreProvider;
+
+ @Mock
+ ModifyStoragePoolAnswer answer;
+
+ @Mock
+ StoragePoolInfo info;
+
+ @Mock
+ PrimaryDataStoreDao primaryStoreDao;
+
+ @Mock
+ StoragePoolVO storagePool;
+
+ @Mock
+ PrimaryDataStoreHelper primaryDataStoreHelper;
+
+ @Before
+ public void initMocks() {
+
+ MockitoAnnotations.initMocks(this);
+
+ List<HostVO> hostList = new ArrayList<HostVO>();
+ HostVO host1 = new HostVO(1L, "aa01", Host.Type.Routing, "192.168.1.1", "255.255.255.0", null, null, null, null, null, null, null, null, null, null,
+ UUID.randomUUID().toString(), Status.Up, "1.0", null, null, 1L, null, 0, 0, "aa", 0, Storage.StoragePoolType.NetworkFilesystem);
+ HostVO host2 = new HostVO(1L, "aa02", Host.Type.Routing, "192.168.1.1", "255.255.255.0", null, null, null, null, null, null, null, null, null, null,
+ UUID.randomUUID().toString(), Status.Up, "1.0", null, null, 1L, null, 0, 0, "aa", 0, Storage.StoragePoolType.NetworkFilesystem);
+
+ host1.setResourceState(ResourceState.Enabled);
+ host2.setResourceState(ResourceState.Disabled);
+ hostList.add(host1);
+ hostList.add(host2);
+
+ when(_dataStoreMgr.getDataStore(anyLong(), eq(DataStoreRole.Primary))).thenReturn(store);
+ when(store.getPoolType()).thenReturn(Storage.StoragePoolType.NetworkFilesystem);
+ when(store.isShared()).thenReturn(true);
+ when(store.getName()).thenReturn("newPool");
+
+ when(_dataStoreProviderMgr.getDataStoreProvider(anyString())).thenReturn(dataStoreProvider);
+ when(dataStoreProvider.getName()).thenReturn("default");
+ ((StorageManagerImpl)storageMgr).registerHostListener("default", hostListener);
+
+ when(_resourceMgr.listAllUpHosts(eq(Host.Type.Routing), anyLong(), anyLong(), anyLong())).thenReturn(hostList);
+ when(agentMgr.easySend(anyLong(), Mockito.any(ModifyStoragePoolCommand.class))).thenReturn(answer);
+ when(answer.getResult()).thenReturn(true);
+ when(answer.getPoolInfo()).thenReturn(info);
+
+ when(info.getLocalPath()).thenReturn("/mnt/1");
+ when(info.getCapacityBytes()).thenReturn(0L);
+ when(info.getAvailableBytes()).thenReturn(0L);
+
+ when(storagePoolHostDao.findByPoolHost(anyLong(), anyLong())).thenReturn(null);
+ when(primaryStoreDao.findById(anyLong())).thenReturn(storagePool);
+ when(primaryStoreDao.update(anyLong(), Mockito.any(StoragePoolVO.class))).thenReturn(true);
+ when(primaryDataStoreHelper.attachCluster(Mockito.any(DataStore.class))).thenReturn(null);
+ }
+
+ @Test
+ public void testAttachCluster() throws Exception {
+ _cloudStackPrimaryDataStoreLifeCycle.attachCluster(store, new ClusterScope(1L, 1L, 1L));
+ verify(storagePoolHostDao,times(2)).persist(Mockito.any(StoragePoolHostVO.class));
+
+ }
+}
diff --git a/plugins/storage/volume/nexenta/pom.xml b/plugins/storage/volume/nexenta/pom.xml
index 9ad7059a6fc..b0bcddc2ca5 100644
--- a/plugins/storage/volume/nexenta/pom.xml
+++ b/plugins/storage/volume/nexenta/pom.xml
@@ -16,7 +16,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/storage/volume/sample/pom.xml b/plugins/storage/volume/sample/pom.xml
index b4673c9fe6f..fed7aae4aa0 100644
--- a/plugins/storage/volume/sample/pom.xml
+++ b/plugins/storage/volume/sample/pom.xml
@@ -16,7 +16,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/storage/volume/solidfire/pom.xml b/plugins/storage/volume/solidfire/pom.xml
index 88f63d7a1fe..57f759b691d 100644
--- a/plugins/storage/volume/solidfire/pom.xml
+++ b/plugins/storage/volume/solidfire/pom.xml
@@ -16,7 +16,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/lifecycle/SolidFireSharedPrimaryDataStoreLifeCycle.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/lifecycle/SolidFireSharedPrimaryDataStoreLifeCycle.java
index a1ea9d0006c..e17219c207d 100644
--- a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/lifecycle/SolidFireSharedPrimaryDataStoreLifeCycle.java
+++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/lifecycle/SolidFireSharedPrimaryDataStoreLifeCycle.java
@@ -371,7 +371,7 @@ public boolean attachCluster(DataStore store, ClusterScope scope) {
PrimaryDataStoreInfo primaryDataStoreInfo = (PrimaryDataStoreInfo)store;
// check if there is at least one host up in this cluster
- List<HostVO> allHosts = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.Routing, primaryDataStoreInfo.getClusterId(),
+ List<HostVO> allHosts = _resourceMgr.listAllUpHosts(Host.Type.Routing, primaryDataStoreInfo.getClusterId(),
primaryDataStoreInfo.getPodId(), primaryDataStoreInfo.getDataCenterId());
if (allHosts.isEmpty()) {
diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/provider/SolidFireHostListener.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/provider/SolidFireHostListener.java
index 082e1a3d2ba..69e1a7995c3 100644
--- a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/provider/SolidFireHostListener.java
+++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/provider/SolidFireHostListener.java
@@ -195,7 +195,7 @@ private void handleKVM(long hostId, long storagePoolId) {
if (hostIdForVm != null) {
HostVO hostForVm = _hostDao.findById(hostIdForVm);
- if (hostForVm.getClusterId().equals(clusterId)) {
+ if (hostForVm != null && hostForVm.getClusterId().equals(clusterId)) {
storagePaths.add(volume.get_iScsiName());
}
}
diff --git a/plugins/user-authenticators/ldap/pom.xml b/plugins/user-authenticators/ldap/pom.xml
index 387fe991a40..49c562e7ab1 100644
--- a/plugins/user-authenticators/ldap/pom.xml
+++ b/plugins/user-authenticators/ldap/pom.xml
@@ -15,7 +15,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/plugins/user-authenticators/md5/pom.xml b/plugins/user-authenticators/md5/pom.xml
index acfb340c565..29d4ace25c7 100644
--- a/plugins/user-authenticators/md5/pom.xml
+++ b/plugins/user-authenticators/md5/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
</project>
diff --git a/plugins/user-authenticators/pbkdf2/pom.xml b/plugins/user-authenticators/pbkdf2/pom.xml
index cfa81b92f6d..bcbcbcea97d 100644
--- a/plugins/user-authenticators/pbkdf2/pom.xml
+++ b/plugins/user-authenticators/pbkdf2/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
</project>
diff --git a/plugins/user-authenticators/plain-text/pom.xml b/plugins/user-authenticators/plain-text/pom.xml
index 41754ef7767..c4011b37d24 100644
--- a/plugins/user-authenticators/plain-text/pom.xml
+++ b/plugins/user-authenticators/plain-text/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
</project>
diff --git a/plugins/user-authenticators/saml2/pom.xml b/plugins/user-authenticators/saml2/pom.xml
index 80476560dcb..890d85e372d 100644
--- a/plugins/user-authenticators/saml2/pom.xml
+++ b/plugins/user-authenticators/saml2/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmd.java b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmd.java
index 2fdf6a1a000..895d12f8359 100644
--- a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmd.java
+++ b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmd.java
@@ -172,6 +172,7 @@ public String authenticate(final String command, final Map<String, Object[]> par
accountResponse.setUserName(user.getUsername());
accountResponse.setDomainId(domain.getUuid());
accountResponse.setDomainName(domain.getName());
+ accountResponse.setDomainPath(domain.getPath());
accountResponse.setAccountName(userAccount.getAccountName());
accountResponse.setIdpId(user.getExternalEntity());
accountResponses.add(accountResponse);
diff --git a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/response/SamlUserAccountResponse.java b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/response/SamlUserAccountResponse.java
index f0927e3f6d3..4952201a96a 100644
--- a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/response/SamlUserAccountResponse.java
+++ b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/response/SamlUserAccountResponse.java
@@ -44,6 +44,10 @@
@Param(description = "The IDP ID")
private String idpId;
+ @SerializedName("domainPath")
+ @Param(description = "The full qualified domain path")
+ private String domainPath;
+
public SamlUserAccountResponse() {
super();
setObjectName("samluseraccount");
@@ -96,4 +100,13 @@ public String getIdpId() {
public void setIdpId(String idpId) {
this.idpId = idpId;
}
+
+ public String getDomainPath() {
+ return domainPath;
+ }
+
+ public void setDomainPath(String domainPath) {
+ this.domainPath = domainPath;
+ }
+
}
diff --git a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2AuthManagerImpl.java b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2AuthManagerImpl.java
index e2d1b888460..d280ed5adaf 100644
--- a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2AuthManagerImpl.java
+++ b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAML2AuthManagerImpl.java
@@ -16,13 +16,34 @@
// under the License.
package org.apache.cloudstack.saml;
-import com.cloud.domain.Domain;
-import com.cloud.user.DomainManager;
-import com.cloud.user.User;
-import com.cloud.user.UserVO;
-import com.cloud.user.dao.UserDao;
-import com.cloud.utils.PropertiesUtil;
-import com.cloud.utils.component.AdapterBase;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SignatureException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.security.spec.InvalidKeySpecException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import javax.inject.Inject;
+import javax.xml.stream.FactoryConfigurationError;
+
import org.apache.cloudstack.api.command.AuthorizeSAMLSSOCmd;
import org.apache.cloudstack.api.command.GetServiceProviderMetaDataCmd;
import org.apache.cloudstack.api.command.ListAndSwitchSAMLAccountCmd;
@@ -34,9 +55,11 @@
import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.framework.security.keystore.KeystoreDao;
import org.apache.cloudstack.framework.security.keystore.KeystoreVO;
+import org.apache.cloudstack.utils.security.CertUtils;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.httpclient.HttpClient;
import org.apache.log4j.Logger;
+import org.bouncycastle.operator.OperatorCreationException;
import org.opensaml.DefaultBootstrap;
import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml2.metadata.ContactPerson;
@@ -61,32 +84,13 @@
import org.opensaml.xml.security.keyinfo.KeyInfoHelper;
import org.springframework.stereotype.Component;
-import javax.inject.Inject;
-import javax.xml.stream.FactoryConfigurationError;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutput;
-import java.io.ObjectOutputStream;
-import java.security.InvalidKeyException;
-import java.security.KeyPair;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.SignatureException;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Timer;
-import java.util.TimerTask;
+import com.cloud.domain.Domain;
+import com.cloud.user.DomainManager;
+import com.cloud.user.User;
+import com.cloud.user.UserVO;
+import com.cloud.user.dao.UserDao;
+import com.cloud.utils.PropertiesUtil;
+import com.cloud.utils.component.AdapterBase;
@Component
public class SAML2AuthManagerImpl extends AdapterBase implements SAML2AuthManager, Configurable {
@@ -141,12 +145,14 @@ protected boolean initSP() {
KeystoreVO keyStoreVO = _ksDao.findByName(SAMLPluginConstants.SAMLSP_KEYPAIR);
if (keyStoreVO == null) {
try {
- KeyPair keyPair = SAMLUtils.generateRandomKeyPair();
- _ksDao.save(SAMLPluginConstants.SAMLSP_KEYPAIR, SAMLUtils.savePrivateKey(keyPair.getPrivate()), SAMLUtils.savePublicKey(keyPair.getPublic()), "samlsp-keypair");
+ KeyPair keyPair = CertUtils.generateRandomKeyPair(4096);
+ _ksDao.save(SAMLPluginConstants.SAMLSP_KEYPAIR,
+ CertUtils.privateKeyToPem(keyPair.getPrivate()),
+ CertUtils.publicKeyToPem(keyPair.getPublic()), "samlsp-keypair");
keyStoreVO = _ksDao.findByName(SAMLPluginConstants.SAMLSP_KEYPAIR);
s_logger.info("No SAML keystore found, created and saved a new Service Provider keypair");
- } catch (NoSuchProviderException | NoSuchAlgorithmException e) {
- s_logger.error("Unable to create and save SAML keypair: " + e.toString());
+ } catch (final NoSuchProviderException | NoSuchAlgorithmException | IOException e) {
+ s_logger.error("Unable to create and save SAML keypair, due to: ", e);
}
}
@@ -160,8 +166,19 @@ protected boolean initSP() {
KeyPair spKeyPair = null;
X509Certificate spX509Key = null;
if (keyStoreVO != null) {
- PrivateKey privateKey = SAMLUtils.loadPrivateKey(keyStoreVO.getCertificate());
- PublicKey publicKey = SAMLUtils.loadPublicKey(keyStoreVO.getKey());
+
+ PrivateKey privateKey = null;
+ try {
+ privateKey = CertUtils.pemToPrivateKey(keyStoreVO.getCertificate());
+ } catch (final InvalidKeySpecException | IOException e) {
+ s_logger.error("Failed to read private key, due to error: ", e);
+ }
+ PublicKey publicKey = null;
+ try {
+ publicKey = CertUtils.pemToPublicKey(keyStoreVO.getKey());
+ } catch (final InvalidKeySpecException | IOException e) {
+ s_logger.error("Failed to read public key, due to error: ", e);
+ }
if (privateKey != null && publicKey != null) {
spKeyPair = new KeyPair(publicKey, privateKey);
KeystoreVO x509VO = _ksDao.findByName(SAMLPluginConstants.SAMLSP_X509CERT);
@@ -174,8 +191,8 @@ protected boolean initSP() {
out.flush();
_ksDao.save(SAMLPluginConstants.SAMLSP_X509CERT, Base64.encodeBase64String(bos.toByteArray()), "", "samlsp-x509cert");
bos.close();
- } catch (NoSuchAlgorithmException | NoSuchProviderException | CertificateEncodingException | SignatureException | InvalidKeyException | IOException e) {
- s_logger.error("SAML Plugin won't be able to use X509 signed authentication");
+ } catch (final NoSuchAlgorithmException | NoSuchProviderException | CertificateException | SignatureException | InvalidKeyException | IOException | OperatorCreationException e) {
+ s_logger.error("SAML plugin won't be able to use X509 signed authentication", e);
}
} else {
try {
diff --git a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAMLUtils.java b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAMLUtils.java
index ec6b2c11e5e..364ef86103f 100644
--- a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAMLUtils.java
+++ b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/saml/SAMLUtils.java
@@ -19,14 +19,41 @@
package org.apache.cloudstack.saml;
-import com.cloud.utils.HttpUtils;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
+import java.net.URLEncoder;
+import java.nio.charset.Charset;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.SecureRandom;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.List;
+import java.util.zip.Deflater;
+import java.util.zip.DeflaterOutputStream;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.FactoryConfigurationError;
+
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.response.LoginCmdResponse;
+import org.apache.cloudstack.utils.security.CertUtils;
import org.apache.log4j.Logger;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.x509.X509V1CertificateGenerator;
+import org.bouncycastle.operator.OperatorCreationException;
import org.joda.time.DateTime;
-import org.joda.time.DateTimeZone;
import org.opensaml.Configuration;
import org.opensaml.DefaultBootstrap;
import org.opensaml.common.SAMLVersion;
@@ -63,41 +90,7 @@
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
-import javax.security.auth.x500.X500Principal;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletResponse;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.stream.FactoryConfigurationError;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.UnsupportedEncodingException;
-import java.math.BigInteger;
-import java.net.URLEncoder;
-import java.nio.charset.Charset;
-import java.security.InvalidKeyException;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.SecureRandom;
-import java.security.Security;
-import java.security.Signature;
-import java.security.SignatureException;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.X509Certificate;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.security.spec.X509EncodedKeySpec;
-import java.util.List;
-import java.util.zip.Deflater;
-import java.util.zip.DeflaterOutputStream;
+import com.cloud.utils.HttpUtils;
public class SAMLUtils {
public static final Logger s_logger = Logger.getLogger(SAMLUtils.class);
@@ -271,89 +264,10 @@ public static String generateSAMLRequestSignature(final String urlEncodedString,
return url;
}
- public static KeyFactory getKeyFactory() {
- KeyFactory keyFactory = null;
- try {
- Security.addProvider(new BouncyCastleProvider());
- keyFactory = KeyFactory.getInstance("RSA", "BC");
- } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
- s_logger.error("Unable to create KeyFactory:" + e.getMessage());
- }
- return keyFactory;
- }
-
- public static String savePublicKey(PublicKey key) {
- try {
- KeyFactory keyFactory = SAMLUtils.getKeyFactory();
- if (keyFactory == null) return null;
- X509EncodedKeySpec spec = keyFactory.getKeySpec(key, X509EncodedKeySpec.class);
- return new String(org.bouncycastle.util.encoders.Base64.encode(spec.getEncoded()), Charset.forName("UTF-8"));
- } catch (InvalidKeySpecException e) {
- s_logger.error("Unable to create KeyFactory:" + e.getMessage());
- }
- return null;
- }
-
- public static String savePrivateKey(PrivateKey key) {
- try {
- KeyFactory keyFactory = SAMLUtils.getKeyFactory();
- if (keyFactory == null) return null;
- PKCS8EncodedKeySpec spec = keyFactory.getKeySpec(key,
- PKCS8EncodedKeySpec.class);
- return new String(org.bouncycastle.util.encoders.Base64.encode(spec.getEncoded()), Charset.forName("UTF-8"));
- } catch (InvalidKeySpecException e) {
- s_logger.error("Unable to create KeyFactory:" + e.getMessage());
- }
- return null;
- }
-
- public static PublicKey loadPublicKey(String publicKey) {
- byte[] sigBytes = org.bouncycastle.util.encoders.Base64.decode(publicKey);
- X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(sigBytes);
- KeyFactory keyFact = SAMLUtils.getKeyFactory();
- if (keyFact == null)
- return null;
- try {
- return keyFact.generatePublic(x509KeySpec);
- } catch (InvalidKeySpecException e) {
- s_logger.error("Unable to create PrivateKey from privateKey string:" + e.getMessage());
- }
- return null;
- }
-
- public static PrivateKey loadPrivateKey(String privateKey) {
- byte[] sigBytes = org.bouncycastle.util.encoders.Base64.decode(privateKey);
- PKCS8EncodedKeySpec pkscs8KeySpec = new PKCS8EncodedKeySpec(sigBytes);
- KeyFactory keyFact = SAMLUtils.getKeyFactory();
- if (keyFact == null)
- return null;
- try {
- return keyFact.generatePrivate(pkscs8KeySpec);
- } catch (InvalidKeySpecException e) {
- s_logger.error("Unable to create PrivateKey from privateKey string:" + e.getMessage());
- }
- return null;
- }
-
- public static KeyPair generateRandomKeyPair() throws NoSuchProviderException, NoSuchAlgorithmException {
- Security.addProvider(new BouncyCastleProvider());
- KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC");
- keyPairGenerator.initialize(4096, new SecureRandom());
- return keyPairGenerator.generateKeyPair();
- }
-
- public static X509Certificate generateRandomX509Certificate(KeyPair keyPair) throws NoSuchAlgorithmException, NoSuchProviderException, CertificateEncodingException, SignatureException, InvalidKeyException {
- DateTime now = DateTime.now(DateTimeZone.UTC);
- X500Principal dnName = new X500Principal("CN=ApacheCloudStack");
- X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
- certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
- certGen.setSubjectDN(dnName);
- certGen.setIssuerDN(dnName);
- certGen.setNotBefore(now.minusDays(1).toDate());
- certGen.setNotAfter(now.plusYears(3).toDate());
- certGen.setPublicKey(keyPair.getPublic());
- certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
- return certGen.generate(keyPair.getPrivate(), "BC");
+ public static X509Certificate generateRandomX509Certificate(KeyPair keyPair) throws NoSuchAlgorithmException, NoSuchProviderException, CertificateException, SignatureException, InvalidKeyException, OperatorCreationException {
+ return CertUtils.generateV1Certificate(keyPair,
+ "CN=ApacheCloudStack", "CN=ApacheCloudStack",
+ 3, "SHA256WithRSA");
}
public static void setupSamlUserCookies(final LoginCmdResponse loginResponse, final HttpServletResponse resp) throws IOException {
diff --git a/plugins/user-authenticators/saml2/test/org/apache/cloudstack/GetServiceProviderMetaDataCmdTest.java b/plugins/user-authenticators/saml2/test/org/apache/cloudstack/GetServiceProviderMetaDataCmdTest.java
index 86009ac4e5c..3df0fccadfa 100644
--- a/plugins/user-authenticators/saml2/test/org/apache/cloudstack/GetServiceProviderMetaDataCmdTest.java
+++ b/plugins/user-authenticators/saml2/test/org/apache/cloudstack/GetServiceProviderMetaDataCmdTest.java
@@ -19,13 +19,22 @@
package org.apache.cloudstack;
-import com.cloud.utils.HttpUtils;
+import java.lang.reflect.Field;
+import java.net.InetAddress;
+import java.security.KeyPair;
+import java.security.cert.X509Certificate;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
import org.apache.cloudstack.api.ApiServerService;
import org.apache.cloudstack.api.auth.APIAuthenticationType;
import org.apache.cloudstack.api.command.GetServiceProviderMetaDataCmd;
import org.apache.cloudstack.saml.SAML2AuthManager;
import org.apache.cloudstack.saml.SAMLProviderMetadata;
import org.apache.cloudstack.saml.SAMLUtils;
+import org.apache.cloudstack.utils.security.CertUtils;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -33,20 +42,7 @@
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import java.lang.reflect.Field;
-import java.security.InvalidKeyException;
-import java.security.KeyPair;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.SignatureException;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateParsingException;
-import java.security.cert.X509Certificate;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
+import com.cloud.utils.HttpUtils;
@RunWith(MockitoJUnitRunner.class)
public class GetServiceProviderMetaDataCmdTest {
@@ -67,7 +63,7 @@
HttpServletRequest req;
@Test
- public void testAuthenticate() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, CertificateParsingException, CertificateEncodingException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException, UnknownHostException {
+ public void testAuthenticate() throws Exception {
GetServiceProviderMetaDataCmd cmd = new GetServiceProviderMetaDataCmd();
Field apiServerField = GetServiceProviderMetaDataCmd.class.getDeclaredField("_apiServer");
@@ -80,7 +76,7 @@ public void testAuthenticate() throws NoSuchFieldException, SecurityException, I
String spId = "someSPID";
String url = "someUrl";
- KeyPair kp = SAMLUtils.generateRandomKeyPair();
+ KeyPair kp = CertUtils.generateRandomKeyPair(4096);
X509Certificate cert = SAMLUtils.generateRandomX509Certificate(kp);
SAMLProviderMetadata providerMetadata = new SAMLProviderMetadata();
diff --git a/plugins/user-authenticators/saml2/test/org/apache/cloudstack/SAMLUtilsTest.java b/plugins/user-authenticators/saml2/test/org/apache/cloudstack/SAMLUtilsTest.java
index bd87831913c..4986d7a2b31 100644
--- a/plugins/user-authenticators/saml2/test/org/apache/cloudstack/SAMLUtilsTest.java
+++ b/plugins/user-authenticators/saml2/test/org/apache/cloudstack/SAMLUtilsTest.java
@@ -19,15 +19,17 @@
package org.apache.cloudstack;
-import junit.framework.TestCase;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
import org.apache.cloudstack.saml.SAMLUtils;
+import org.apache.cloudstack.utils.security.CertUtils;
import org.junit.Test;
import org.opensaml.saml2.core.AuthnRequest;
import org.opensaml.saml2.core.LogoutRequest;
-import java.security.KeyPair;
-import java.security.PrivateKey;
-import java.security.PublicKey;
+import junit.framework.TestCase;
public class SAMLUtilsTest extends TestCase {
@@ -60,13 +62,13 @@ public void testBuildLogoutRequest() throws Exception {
@Test
public void testX509Helpers() throws Exception {
- KeyPair keyPair = SAMLUtils.generateRandomKeyPair();
+ KeyPair keyPair = CertUtils.generateRandomKeyPair(4096);
- String privateKeyString = SAMLUtils.savePrivateKey(keyPair.getPrivate());
- String publicKeyString = SAMLUtils.savePublicKey(keyPair.getPublic());
+ String privateKeyString = CertUtils.privateKeyToPem(keyPair.getPrivate());
+ String publicKeyString = CertUtils.publicKeyToPem(keyPair.getPublic());
- PrivateKey privateKey = SAMLUtils.loadPrivateKey(privateKeyString);
- PublicKey publicKey = SAMLUtils.loadPublicKey(publicKeyString);
+ PrivateKey privateKey = CertUtils.pemToPrivateKey(privateKeyString);
+ PublicKey publicKey = CertUtils.pemToPublicKey(publicKeyString);
assertTrue(privateKey.equals(keyPair.getPrivate()));
assertTrue(publicKey.equals(keyPair.getPublic()));
diff --git a/plugins/user-authenticators/saml2/test/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmdTest.java b/plugins/user-authenticators/saml2/test/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmdTest.java
index 36140f2bedd..2ce88414b40 100644
--- a/plugins/user-authenticators/saml2/test/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmdTest.java
+++ b/plugins/user-authenticators/saml2/test/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmdTest.java
@@ -21,12 +21,16 @@
import static org.junit.Assert.assertFalse;
-import com.cloud.domain.Domain;
-import com.cloud.user.AccountService;
-import com.cloud.user.DomainManager;
-import com.cloud.user.UserAccountVO;
-import com.cloud.user.dao.UserAccountDao;
-import com.cloud.utils.HttpUtils;
+import java.lang.reflect.Field;
+import java.net.InetAddress;
+import java.security.KeyPair;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
import org.apache.cloudstack.api.ApiServerService;
import org.apache.cloudstack.api.BaseCmd;
@@ -36,6 +40,7 @@
import org.apache.cloudstack.saml.SAMLPluginConstants;
import org.apache.cloudstack.saml.SAMLProviderMetadata;
import org.apache.cloudstack.saml.SAMLUtils;
+import org.apache.cloudstack.utils.security.CertUtils;
import org.joda.time.DateTime;
import org.junit.Assert;
import org.junit.Test;
@@ -64,16 +69,12 @@
import org.opensaml.saml2.core.impl.StatusCodeBuilder;
import org.opensaml.saml2.core.impl.SubjectBuilder;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
-import java.lang.reflect.Field;
-import java.security.KeyPair;
-import java.security.cert.X509Certificate;
-import java.util.HashMap;
-import java.util.Map;
-import java.net.InetAddress;
+import com.cloud.domain.Domain;
+import com.cloud.user.AccountService;
+import com.cloud.user.DomainManager;
+import com.cloud.user.UserAccountVO;
+import com.cloud.user.dao.UserAccountDao;
+import com.cloud.utils.HttpUtils;
@RunWith(MockitoJUnitRunner.class)
public class SAML2LoginAPIAuthenticatorCmdTest {
@@ -158,7 +159,7 @@ public void testAuthenticate() throws Exception {
userAccountDaoField.setAccessible(true);
userAccountDaoField.set(cmd, userAccountDao);
- KeyPair kp = SAMLUtils.generateRandomKeyPair();
+ KeyPair kp = CertUtils.generateRandomKeyPair(4096);
X509Certificate cert = SAMLUtils.generateRandomX509Certificate(kp);
SAMLProviderMetadata providerMetadata = new SAMLProviderMetadata();
diff --git a/plugins/user-authenticators/saml2/test/org/apache/cloudstack/api/command/SAML2LogoutAPIAuthenticatorCmdTest.java b/plugins/user-authenticators/saml2/test/org/apache/cloudstack/api/command/SAML2LogoutAPIAuthenticatorCmdTest.java
index cbfcc55c540..09391c5d7d2 100644
--- a/plugins/user-authenticators/saml2/test/org/apache/cloudstack/api/command/SAML2LogoutAPIAuthenticatorCmdTest.java
+++ b/plugins/user-authenticators/saml2/test/org/apache/cloudstack/api/command/SAML2LogoutAPIAuthenticatorCmdTest.java
@@ -19,11 +19,19 @@
package org.apache.cloudstack.api.command;
-import com.cloud.utils.HttpUtils;
+import java.lang.reflect.Field;
+import java.net.InetAddress;
+import java.security.cert.X509Certificate;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
import org.apache.cloudstack.api.ApiServerService;
import org.apache.cloudstack.api.auth.APIAuthenticationType;
import org.apache.cloudstack.saml.SAML2AuthManager;
import org.apache.cloudstack.saml.SAMLUtils;
+import org.apache.cloudstack.utils.security.CertUtils;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -31,12 +39,7 @@
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import java.lang.reflect.Field;
-import java.security.cert.X509Certificate;
-import java.net.InetAddress;
+import com.cloud.utils.HttpUtils;
@RunWith(MockitoJUnitRunner.class)
public class SAML2LogoutAPIAuthenticatorCmdTest {
@@ -70,7 +73,7 @@ public void testAuthenticate() throws Exception {
String spId = "someSPID";
String url = "someUrl";
- X509Certificate cert = SAMLUtils.generateRandomX509Certificate(SAMLUtils.generateRandomKeyPair());
+ X509Certificate cert = SAMLUtils.generateRandomX509Certificate(CertUtils.generateRandomKeyPair(4096));
Mockito.when(session.getAttribute(Mockito.anyString())).thenReturn(null);
cmd.authenticate("command", null, session, InetAddress.getByName("127.0.0.1"), HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
diff --git a/plugins/user-authenticators/sha256salted/pom.xml b/plugins/user-authenticators/sha256salted/pom.xml
index 00d3e6ae3ce..cf1a8dd08a7 100644
--- a/plugins/user-authenticators/sha256salted/pom.xml
+++ b/plugins/user-authenticators/sha256salted/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
</project>
diff --git a/pom.xml b/pom.xml
index 9e077d137dd..45095d4c30e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -30,14 +30,14 @@
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Apache CloudStack</name>
- <description>Apache CloudStack is an IaaS (?Infrastructure as a Service?) cloud orchestration platform.</description>
+ <description>Apache CloudStack is an IaaS ("Infrastructure as a Service") cloud orchestration platform.</description>
<url>http://www.cloudstack.org</url>
<scm>
- <connection>scm:git:https://git-wip-us.apache.org/repos/asf/cloudstack.git</connection>
- <developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/cloudstack.git</developerConnection>
+ <connection>scm:git:https://gitbox.apache.org/repos/asf/cloudstack.git</connection>
+ <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/cloudstack.git</developerConnection>
</scm>
<issueManagement>
<system>jira</system>
@@ -51,34 +51,33 @@
<cs.log4j.version>1.2.17</cs.log4j.version>
<cs.log4j.extras.version>1.2.17</cs.log4j.extras.version>
- <cs.cglib.version>3.2.4</cs.cglib.version>
+ <cs.cglib.version>3.2.5</cs.cglib.version>
<cs.dbcp.version>1.4</cs.dbcp.version>
<cs.pool.version>1.6</cs.pool.version>
<cs.codec.version>1.10</cs.codec.version>
<cs.configuration.version>1.10</cs.configuration.version>
- <cs.collections.version>3.2.2</cs.collections.version>
<cs.logging.version>1.1.1</cs.logging.version>
<cs.discovery.version>0.5</cs.discovery.version>
<cs.ejb.version>3.0</cs.ejb.version>
<!-- do not forget to also upgrade hamcrest library with junit -->
<cs.junit.version>4.12</cs.junit.version>
<cs.hamcrest.version>1.3</cs.hamcrest.version>
- <cs.junit.dataprovider.version>1.12.0</cs.junit.dataprovider.version>
- <cs.bcprov.version>1.55</cs.bcprov.version>
+ <cs.junit.dataprovider.version>1.13.1</cs.junit.dataprovider.version>
+ <cs.bcprov.version>1.58</cs.bcprov.version>
<cs.jsch.version>0.1.54</cs.jsch.version>
- <cs.jpa.version>2.1.1</cs.jpa.version>
+ <cs.jpa.version>2.2.0</cs.jpa.version>
<cs.jasypt.version>1.9.2</cs.jasypt.version>
- <cs.trilead.version>1.0.0-build220</cs.trilead.version>
+ <cs.trilead.version>1.0.0-build221</cs.trilead.version>
<cs.ehcache.version>2.6.11</cs.ehcache.version>
<cs.gson.version>1.7.2</cs.gson.version>
<cs.guava-testlib.version>18.0</cs.guava-testlib.version>
- <cs.guava.version>20.0</cs.guava.version>
+ <cs.guava.version>23.2-jre</cs.guava.version>
<cs.xapi.version>6.2.0-3.1</cs.xapi.version>
- <cs.httpclient.version>4.5.2</cs.httpclient.version>
- <cs.httpcore.version>4.4.5</cs.httpcore.version>
+ <cs.httpclient.version>4.5.3</cs.httpclient.version>
+ <cs.httpcore.version>4.4.8</cs.httpcore.version>
<cs.commons-httpclient.version>3.1</cs.commons-httpclient.version>
<cs.mysql.version>5.1.34</cs.mysql.version>
- <cs.xstream.version>1.4.9</cs.xstream.version>
+ <cs.xstream.version>1.4.10</cs.xstream.version>
<cs.xmlrpc.version>3.1.3</cs.xmlrpc.version>
<cs.mail.version>1.5.0-b01</cs.mail.version>
<cs.axis.version>1.4</cs.axis.version>
@@ -86,24 +85,24 @@
<cs.rampart.version>1.5.1</cs.rampart.version>
<cs.axiom.version>1.2.8</cs.axiom.version>
<cs.neethi.version>2.0.4</cs.neethi.version>
- <cs.servlet.version>3.1.0</cs.servlet.version>
+ <cs.servlet.version>4.0.0</cs.servlet.version>
<cs.jstl.version>1.2</cs.jstl.version>
<cs.jstl-api.version>1.2.1</cs.jstl-api.version>
<cs.selenium.server.version>1.0-20081010.060147</cs.selenium.server.version>
<cs.vmware.api.version>6.0</cs.vmware.api.version>
- <org.springframework.version>4.3.4.RELEASE</org.springframework.version>
+ <org.springframework.version>5.0.0.RELEASE</org.springframework.version>
<cs.mockito.version>1.10.19</cs.mockito.version>
<cs.powermock.version>1.6.4</cs.powermock.version>
- <cs.aws.sdk.version>1.11.61</cs.aws.sdk.version>
- <cs.jackson.version>2.7.1</cs.jackson.version>
+ <cs.aws.sdk.version>1.11.213</cs.aws.sdk.version>
+ <cs.jackson.version>2.9.2</cs.jackson.version>
<cs.lang.version>2.6</cs.lang.version>
<cs.commons-lang3.version>3.4</cs.commons-lang3.version>
<cs.commons-io.version>2.5</cs.commons-io.version>
- <cs.commons-fileupload.version>1.3.2</cs.commons-fileupload.version>
- <cs.commons-collections.version>3.2.2</cs.commons-collections.version>
- <cs.commons-validator.version>1.5.1</cs.commons-validator.version>
- <cs.reflections.version>0.9.10</cs.reflections.version>
- <cs.javassist.version>3.18.2-GA</cs.javassist.version>
+ <cs.commons-fileupload.version>1.3.3</cs.commons-fileupload.version>
+ <cs.commons-collections.version>4.1</cs.commons-collections.version>
+ <cs.commons-validator.version>1.6</cs.commons-validator.version>
+ <cs.reflections.version>0.9.11</cs.reflections.version>
+ <cs.javassist.version>3.22.0-GA</cs.javassist.version>
<cs.java-ipv6.version>0.16</cs.java-ipv6.version>
<cs.replace.properties>build/replace.properties</cs.replace.properties>
<cs.libvirt-java.version>0.5.1</cs.libvirt-java.version>
@@ -118,12 +117,13 @@
<cs.opensaml.version>2.6.4</cs.opensaml.version>
<cs.xml-apis.version>1.4.01</cs.xml-apis.version>
<cs.joda-time.version>2.8.1</cs.joda-time.version>
- <cs.batik.version>1.8</cs.batik.version>
- <cs.servicemix.version>2.3.4_1</cs.servicemix.version>
- <cs.jetty.version>9.2.20.v20161216</cs.jetty.version>
- <cs.cxf.version>3.1.4</cs.cxf.version>
- <cs.groovy.version>2.4.7</cs.groovy.version>
+ <cs.batik.version>1.9.1</cs.batik.version>
+ <cs.servicemix.version>2.5.7_1</cs.servicemix.version>
+ <cs.cxf.version>3.2.0</cs.cxf.version>
+ <cs.groovy.version>2.4.12</cs.groovy.version>
<cs.nitro.version>10.1</cs.nitro.version>
+ <cs.wiremock.version>2.8.0</cs.wiremock.version>
+ <cs.jetty.version>9.2.22.v20170606</cs.jetty.version>
</properties>
<distributionManagement>
@@ -225,6 +225,11 @@
<artifactId>bcprov-jdk15on</artifactId>
<version>${cs.bcprov.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcpkix-jdk15on</artifactId>
+ <version>${cs.bcprov.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-css</artifactId>
@@ -241,8 +246,8 @@
<version>${cs.batik.version}</version>
</dependency>
<dependency>
- <groupId>commons-collections</groupId>
- <artifactId>commons-collections</artifactId>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-collections4</artifactId>
<version>${cs.commons-collections.version}</version>
</dependency>
<dependency>
@@ -319,7 +324,12 @@
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
- <artifactId>aws-java-sdk</artifactId>
+ <artifactId>aws-java-sdk-core</artifactId>
+ <version>${cs.aws.sdk.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.amazonaws</groupId>
+ <artifactId>aws-java-sdk-s3</artifactId>
<version>${cs.aws.sdk.version}</version>
</dependency>
<dependency>
@@ -437,12 +447,12 @@
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
- <version>1.8.10</version>
+ <version>1.8.11</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
- <version>1.8.10</version>
+ <version>1.8.11</version>
</dependency>
<dependency>
<groupId>org.apache.axis</groupId>
@@ -474,6 +484,31 @@
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.22</version>
</dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <version>${cs.jetty.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlets</artifactId>
+ <version>${cs.jetty.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-webapp</artifactId>
+ <version>${cs.jetty.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-jmx</artifactId>
+ <version>${cs.jetty.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-util</artifactId>
+ <version>${cs.jetty.version}</version>
+ </dependency>
</dependencies>
</dependencyManagement>
@@ -781,11 +816,6 @@
</lifecycleMappingMetadata>
</configuration>
</plugin>
- <plugin>
- <groupId>org.apache.tomcat.maven</groupId>
- <artifactId>tomcat7-maven-plugin</artifactId>
- <version>2.2</version>
- </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
@@ -955,6 +985,7 @@
<version>2.5</version>
<configuration>
<archive>
+ <addMavenDescriptor>false</addMavenDescriptor>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
diff --git a/python/bindir/cloud-grab-dependent-library-versions b/python/bindir/cloud-grab-dependent-library-versions
index d485cb05e3b..f07ec1a46d5 100755
--- a/python/bindir/cloud-grab-dependent-library-versions
+++ b/python/bindir/cloud-grab-dependent-library-versions
@@ -18,7 +18,7 @@
import subprocess
-depLibraries = ['python', 'bzip2', 'gzip', 'unzip', 'openssh-clients', 'nfs-utils', 'wget', 'tomcat6', 'ws-commons-util', 'commons-dbcp',
+depLibraries = ['python', 'bzip2', 'gzip', 'unzip', 'openssh-clients', 'nfs-utils', 'wget', 'ws-commons-util', 'commons-dbcp',
'commons-collections', 'commons-httpclient', 'jpackage-utils', 'MySQL-python', 'python-paramiko', 'ipmitool', 'commons-httpclient', 'commons-collections',
'commons-pool', 'commons-dbcp', 'jakarta-commons-logging', 'java-*-openjdk']
diff --git a/python/lib/cloudutils/globalEnv.py b/python/lib/cloudutils/globalEnv.py
index f3a40b76fc9..1389bab9020 100644
--- a/python/lib/cloudutils/globalEnv.py
+++ b/python/lib/cloudutils/globalEnv.py
@@ -24,8 +24,6 @@ def __init__(self):
self.noStart = False
#myCloud/Agent/Console
self.agentMode = None
- #Tomcat6/Tomcat7
- self.svrConf = None
#debug
self.debug = False
#management server IP
diff --git a/python/lib/cloudutils/networkConfig.py b/python/lib/cloudutils/networkConfig.py
index 41ef9d93ed2..b3ae26951ba 100644
--- a/python/lib/cloudutils/networkConfig.py
+++ b/python/lib/cloudutils/networkConfig.py
@@ -154,7 +154,7 @@ def getDevInfo(dev):
if networkConfig.isBridgePort(dev):
type = "brport"
- elif networkConfig.isBridge(dev):
+ elif networkConfig.isBridge(dev) or networkConfig.isOvsBridge(dev):
type = "bridge"
else:
type = "dev"
diff --git a/python/lib/cloudutils/serviceConfigServer.py b/python/lib/cloudutils/serviceConfigServer.py
index c975f6eb9cf..17485721710 100644
--- a/python/lib/cloudutils/serviceConfigServer.py
+++ b/python/lib/cloudutils/serviceConfigServer.py
@@ -71,81 +71,14 @@ def checkHostName():
#add DNAT 443 to 8250
if not bash("iptables-save |grep PREROUTING | grep 8250").isSuccess():
bash("iptables -A PREROUTING -t nat -p tcp --dport 443 -j REDIRECT --to-port 8250 ")
-
- #generate keystore
- keyPath = "/var/cloudstack/management/web.keystore"
- if not os.path.exists(keyPath):
- cmd = bash("keytool -genkey -keystore %s -storepass \"cloud.com\" -keypass \"cloud.com\" -validity 3650 -dname cn=\"Cloudstack User\",ou=\"mycloud.cloud.com\",o=\"mycloud.cloud.com\",c=\"Unknown\""%keyPath)
-
- if not cmd.isSuccess():
- raise CloudInternalException(cmd.getErrMsg())
- if not self.syscfg.env.svrConf == "Tomcat7":
- cfo = configFileOps("/etc/cloudstack/management/tomcat6.conf", self)
- cfo.add_lines("JAVA_OPTS+=\" -Djavax.net.ssl.trustStore=%s \""%keyPath)
elif self.syscfg.env.svrMode == "HttpsServer":
- if self.syscfg.env.svrConf == "Tomcat7":
- if not os.path.exists("/etc/cloudstack/management/server7-ssl.xml"):
- raise CloudRuntimeException("Cannot find /etc/cloudstack/management/server7-ssl.xml, https enable failed")
- if os.path.exists("/etc/cloudstack/management/server.xml"):
- bash("rm -f /etc/cloudstack/management/server.xml")
- bash("ln -s /etc/cloudstack/management/server7-ssl.xml /etc/cloudstack/management/server.xml")
- if os.path.exists("/usr/share/tomcat7/bin"):
- bash("rm -f /usr/share/cloudstack-management/bin")
- bash("ln -s /usr/share/tomcat7/bin /usr/share/cloudstack-management/bin")
- if os.path.exists("/usr/share/tomcat7/lib"):
- bash("rm -f /usr/share/cloudstack-management/lib")
- bash("ln -s /usr/share/tomcat7/lib /usr/share/cloudstack-management/lib")
- else:
- if not os.path.exists("/etc/cloudstack/management/server-ssl.xml") or not os.path.exists("/etc/cloudstack/management/tomcat6-ssl.conf"):
- raise CloudRuntimeException("Cannot find /etc/cloudstack/management/server-ssl.xml or /etc/cloudstack/management/tomcat6-ssl.conf, https enable failed")
- if os.path.exists("/etc/cloudstack/management/server.xml"):
- bash("rm -f /etc/cloudstack/management/server.xml")
- if os.path.exists("/etc/cloudstack/management/tomcat6.conf"):
- bash("rm -f /etc/cloudstack/management/tomcat6.conf")
- bash("ln -s /etc/cloudstack/management/server-ssl.xml /etc/cloudstack/management/server.xml")
- bash("ln -s /etc/cloudstack/management/tomcat6-ssl.conf /etc/cloudstack/management/tomcat6.conf")
- if os.path.exists("/usr/share/tomcat6/bin"):
- bash("rm -f /usr/share/cloudstack-management/bin")
- bash("ln -s /usr/share/tomcat6/bin /usr/share/cloudstack-management/bin")
- if os.path.exists("/usr/share/tomcat6/lib"):
- bash("rm -f /usr/share/cloudstack-management/lib")
- bash("ln -s /usr/share/tomcat6/lib /usr/share/cloudstack-management/lib")
- if not bash("iptables-save |grep PREROUTING | grep 6443").isSuccess():
- bash("iptables -A PREROUTING -t nat -p tcp --dport 443 -j REDIRECT --to-port 6443")
- else:
- if self.syscfg.env.svrConf == "Tomcat7":
- if not os.path.exists("/etc/cloudstack/management/server7-nonssl.xml"):
- raise CloudRuntimeException("Cannot find /etc/cloudstack/management/server7-nonssl.xml, https enable failed")
- if os.path.exists("/etc/cloudstack/management/server.xml"):
- bash("rm -f /etc/cloudstack/management/server.xml")
- bash("ln -s /etc/cloudstack/management/server7-nonssl.xml /etc/cloudstack/management/server.xml")
- if os.path.exists("/usr/share/tomcat7/bin"):
- bash("rm -f /usr/share/cloudstack-management/bin")
- bash("ln -s /usr/share/tomcat7/bin /usr/share/cloudstack-management/bin")
- if os.path.exists("/usr/share/tomcat7/lib"):
- bash("rm -f /usr/share/cloudstack-management/lib")
- bash("ln -s /usr/share/tomcat7/lib /usr/share/cloudstack-management/lib")
- else:
- if not os.path.exists("/etc/cloudstack/management/server-nonssl.xml") or not os.path.exists("/etc/cloudstack/management/tomcat6-nonssl.conf"):
- raise CloudRuntimeException("Cannot find /etc/cloudstack/management/server-nonssl.xml or /etc/cloudstack/management/tomcat6-nonssl.conf, https enable failed")
- if os.path.exists("/etc/cloudstack/management/server.xml"):
- bash("rm -f /etc/cloudstack/management/server.xml")
- if os.path.exists("/etc/cloudstack/management/tomcat6.conf"):
- bash("rm -f /etc/cloudstack/management/tomcat6.conf")
- bash("ln -s /etc/cloudstack/management/server-nonssl.xml /etc/cloudstack/management/server.xml")
- bash("ln -s /etc/cloudstack/management/tomcat6-nonssl.conf /etc/cloudstack/management/tomcat6.conf")
- if os.path.exists("/usr/share/tomcat6/bin"):
- bash("rm -f /usr/share/cloudstack-management/bin")
- bash("ln -s /usr/share/tomcat6/bin /usr/share/cloudstack-management/bin")
- if os.path.exists("/usr/share/tomcat6/lib"):
- bash("rm -f /usr/share/cloudstack-management/lib")
- bash("ln -s /usr/share/tomcat6/lib /usr/share/cloudstack-management/lib")
+ if not bash("iptables-save |grep PREROUTING | grep 8443").isSuccess():
+ bash("iptables -A PREROUTING -t nat -p tcp --dport 443 -j REDIRECT --to-port 8443")
bash("touch /var/run/cloudstack-management.pid")
bash("chown cloud.cloud /var/run/cloudstack-management.pid")
- #distro like sl 6.1 needs this folder, or tomcat6 failed to start
checkHostName()
+ bash("mkdir -p /var/lib/cloudstack/")
bash("chown cloud:cloud -R /var/lib/cloudstack/")
- bash("chmod +x -R /usr/share/cloudstack-management/webapps/client/WEB-INF/classes/scripts/")
#set max process per account is unlimited
if os.path.exists("/etc/security/limits.conf"):
cfo = configFileOps("/etc/security/limits.conf")
@@ -153,14 +86,6 @@ def checkHostName():
cfo.add_lines("cloud hard nproc -1\n")
cfo.save()
- try:
- if self.syscfg.env.svrConf == "Tomcat7":
- self.syscfg.svo.disableService("tomcat")
- else:
- self.syscfg.svo.disableService("tomcat6")
- except:
- pass
-
if self.syscfg.env.noStart == False:
self.syscfg.svo.stopService("cloudstack-management")
if self.syscfg.svo.enableService("cloudstack-management"):
diff --git a/quickcloud/pom.xml b/quickcloud/pom.xml
index 601781824b0..efccb96596a 100644
--- a/quickcloud/pom.xml
+++ b/quickcloud/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-maven-standard</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../maven-standard/pom.xml</relativePath>
</parent>
</project>
diff --git a/scripts/common/keys/ssl-keys.py b/scripts/common/keys/ssl-keys.py
deleted file mode 100644
index d6804cca19d..00000000000
--- a/scripts/common/keys/ssl-keys.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/bin/bash
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-
-# Copies keys that enable SSH communication with system vms
-# $1 = new public key
-# $2 = new private key
-'''
-All imports go here...
-'''
-from subprocess import call
-import socket
-import sys
-import os
-import subprocess
-import traceback
-
-def generateSSLKey(outputPath):
- logf = open("ssl-keys.log", "w")
- hostName = socket.gethostbyname(socket.gethostname())
- keyFile = outputPath + os.sep + "cloudmanagementserver.keystore"
- logf.write("HostName = %s\n" % hostName)
- logf.write("OutputPath = %s\n" % keyFile)
- dname='cn="Cloudstack User",ou="' + hostName + '",o="' + hostName + '",c="Unknown"';
- logf.write("dname = %s\n" % dname)
- logf.flush()
- try :
- return_code = subprocess.Popen(["keytool", "-genkey", "-keystore", keyFile, "-storepass", "vmops.com", "-keypass", "vmops.com", "-keyalg", "RSA", "-validity", "3650", "-dname", dname],shell=True,stdout=logf, stderr=logf)
- return_code.wait()
- except OSError as e:
- logf.flush()
- traceback.print_exc(file=logf)
- logf.flush()
- logf.write("SSL key generated is : %s" % return_code)
- logf.flush()
-
-argsSize=len(sys.argv)
-if argsSize != 2:
- print("Usage: ssl-keys.py <SSL File Key Path>")
- sys.exit(None)
-sslKeyPath=sys.argv[1]
-
-generateSSLKey(sslKeyPath)
\ No newline at end of file
diff --git a/scripts/installer/createtmplt.sh b/scripts/installer/createtmplt.sh
index 67b25c3b923..c187c5fcb12 100755
--- a/scripts/installer/createtmplt.sh
+++ b/scripts/installer/createtmplt.sh
@@ -39,6 +39,7 @@ fi
verify_cksum() {
digestalgo=""
+# NOTE this will only work with 0-padded checksums
case ${#1} in
32) digestalgo="md5sum" ;;
40) digestalgo="sha1sum" ;;
diff --git a/scripts/installer/createvolume.sh b/scripts/installer/createvolume.sh
index 00ee5e5e773..c7f11dc237c 100755
--- a/scripts/installer/createvolume.sh
+++ b/scripts/installer/createvolume.sh
@@ -40,6 +40,7 @@ fi
verify_cksum() {
digestalgo=""
+# NOTE this will only work with 0-padded checksums
case ${#1} in
32) digestalgo="md5sum" ;;
40) digestalgo="sha1sum" ;;
diff --git a/scripts/installer/windows/acs.wxs b/scripts/installer/windows/acs.wxs
index fa8ff41a8a2..6f2aec07d97 100644
--- a/scripts/installer/windows/acs.wxs
+++ b/scripts/installer/windows/acs.wxs
@@ -255,9 +255,6 @@
<CustomAction Id="SetuptoolsInstallation" Directory='INSTALLDIR'
ExeCommand='[PYTHON_HOME]\python "[INSTALLDIR]\ez_setup.py"'
Execute="deferred" Return="check" />
- <CustomAction Id="GenerateSSLKey" Directory='CSMANAGEMENT'
- ExeCommand='[PYTHON_HOME]\python "[CSMANAGEMENT]\webapps\client\WEB-INF\classes\scripts\common\keys\ssl-keys.py" "[CSMANAGEMENT]\lib"'
- Execute="deferred" Return="check" />
<CustomAction Id="DbHostWithPort" Execute="immediate" Property="DB_HOSTNAME" Value="[DB_HOSTNAME]:[DB_PORT]" />
<CustomAction Id="DeployDB" Directory='CSMANAGEMENT'
ExeCommand='[PYTHON_HOME]\python "[INSTALLDIR]\scripts\cloud-setup-databases" [DB_USERNAME]:[DB_PASSWORD]@[DB_HOSTNAME] --deploy-as=root:[DB_ROOT_PASSWORD] -c "[CSMANAGEMENT]\lib" -f "[CSMANAGEMENT]\setup" -j "[CSMANAGEMENT]\webapps\client\WEB-INF\lib\jasypt-1.9.2.jar" -n "[CSMANAGEMENT]\lib\key" -b "[MYSQL]\bin"'
diff --git a/scripts/installer/windows/client.wxs b/scripts/installer/windows/client.wxs
index 91b15fbd950..8c5cdc7807c 100644
--- a/scripts/installer/windows/client.wxs
+++ b/scripts/installer/windows/client.wxs
@@ -586,9 +586,6 @@
<Component Id="cmp6001B626D853C4E4FAB8511246B8D2B4" Guid="{DB90C42E-A2DC-4742-8BC8-49AF7556E7D1}">
<File Id="fil5A0CF0340938B7ACC3B69C1353BDC625" KeyPath="yes" Source="!(wix.SourceClient)\WEB-INF\classes\classpath.conf" />
</Component>
- <Component Id="cmp71D36BFB6B214FAAD323C31A1CE3BC19" Guid="{EF4C61E1-F77E-4E4D-80EA-131511E0804E}">
- <File Id="fil44B623C422B90349A635A113C5F4D417" KeyPath="yes" Source="!(wix.SourceClient)\WEB-INF\classes\cloudmanagementserver.keystore" />
- </Component>
<Component Id="cmp68E096BB729948107692341D8202CC5A" Guid="{0D5D3AF3-0BC0-48EE-ABA3-AF07535169BF}">
<File Id="fil3E9BCB1A8CB8F8415FE3E71B65A94878" KeyPath="yes" Source="!(wix.SourceClient)\WEB-INF\classes\context.xml" />
</Component>
@@ -1452,9 +1449,6 @@
<Component Id="cmpE79D8DE0A3F5641D63029C9C5BB84D0D" Guid="{71A421D6-EC6B-4410-BEB8-D8A13CBF2F76}">
<File Id="fil26BE9842DE6416E8946A2295439E129D" KeyPath="yes" Source="!(wix.SourceClient)\WEB-INF\lib\cloud-plugin-network-internallb-4.4.0-SNAPSHOT.jar" />
</Component>
- <Component Id="cmpA6C72B638E002C5141944F120B6B9711" Guid="{02C8CA2E-826F-452D-AC54-2E8787451C2B}">
- <File Id="filB57FEF496D3CF0EDD6B9DC7FA5E08D31" KeyPath="yes" Source="!(wix.SourceClient)\WEB-INF\lib\cloud-plugin-network-midonet-4.4.0-SNAPSHOT.jar" />
- </Component>
<Component Id="cmpBA53547354F4749AB6DB53E652729729" Guid="{0026D30B-04AA-45D9-9582-743650497E99}">
<File Id="filC6F3205D9E0721B202FECAD231D0E72B" KeyPath="yes" Source="!(wix.SourceClient)\WEB-INF\lib\cloud-plugin-network-netscaler-4.4.0-SNAPSHOT.jar" />
</Component>
@@ -1707,9 +1701,6 @@
<Component Id="cmp6114379A976905B2F2770C6E5934AC79" Guid="{8CCECB3F-062A-439E-863E-950BA2B0062F}">
<File Id="fil6A0D7E786C6E6FD2FF2C2D52A4A7FB3E" KeyPath="yes" Source="!(wix.SourceClient)\WEB-INF\lib\mail-1.4.jar" />
</Component>
- <Component Id="cmpCF3E965E2D26D7E48F44F280084D6836" Guid="{7A9845D3-BF3E-495C-9CFB-BA1D37199DAB}">
- <File Id="fil7B2A7C3FF6D92CABA0F6015F9D1FCB7E" KeyPath="yes" Source="!(wix.SourceClient)\WEB-INF\lib\midonet-client-1.1.0.jar" />
- </Component>
<Component Id="cmp2210FF2D22610D7C6B5B50F74A6CCFF6" Guid="{8B4D96E1-E8D0-415D-BC1E-0D6B9C2896EB}">
<File Id="fil79A9A35E5D30D89644135E92F334EBC6" KeyPath="yes" Source="!(wix.SourceClient)\WEB-INF\lib\nekohtml-1.9.12.jar" />
</Component>
diff --git a/scripts/network/domr/router_proxy.sh b/scripts/network/domr/router_proxy.sh
index f9cb7ca0157..945ca968d26 100755
--- a/scripts/network/domr/router_proxy.sh
+++ b/scripts/network/domr/router_proxy.sh
@@ -35,13 +35,11 @@ check_gw() {
cert="/root/.ssh/id_rsa.cloud"
-script=$1
-shift
-
-domRIp=$1
-shift
+script="$1"
+domRIp="$2"
check_gw "$domRIp"
-ssh -p 3922 -q -o StrictHostKeyChecking=no -i $cert root@$domRIp "/opt/cloud/bin/$script $*"
+ssh -p 3922 -q -o StrictHostKeyChecking=no -i $cert root@$domRIp "/opt/cloud/bin/$script ${@:3}"
+
exit $?
diff --git a/scripts/storage/qcow2/createtmplt.sh b/scripts/storage/qcow2/createtmplt.sh
index 11645250e55..b05550c14bb 100755
--- a/scripts/storage/qcow2/createtmplt.sh
+++ b/scripts/storage/qcow2/createtmplt.sh
@@ -21,7 +21,7 @@
# createtmplt.sh -- install a template
usage() {
- printf "Usage: %s: -t <template-fs> -n <templatename> -f <root disk file> -s <size in Gigabytes> -c <md5 cksum> -d <descr> -h [-u]\n" $(basename $0) >&2
+ printf "Usage: %s: -t <template-fs> -n <templatename> -f <root disk file> -s <size in Gigabytes> -c <snapshot name> -d <descr> -h [-u]\n" $(basename $0) >&2
}
@@ -37,27 +37,6 @@ then
fi
fi
-
-verify_cksum() {
- digestalgo=""
- case ${#1} in
- 32) digestalgo="md5sum" ;;
- 40) digestalgo="sha1sum" ;;
- 56) digestalgo="sha224sum" ;;
- 64) digestalgo="sha256sum" ;;
- 96) digestalgo="sha384sum" ;;
- 128) digestalgo="sha512sum" ;;
- *) echo "Please provide valid cheksum" ; exit 3 ;;
- esac
- echo "$1 $2" | $digestalgo -c --status
- #printf "$1\t$2" | $digestalgo -c --status
- if [ $? -gt 0 ]
- then
- printf "Checksum failed, not proceeding with install\n"
- exit 3
- fi
-}
-
untar() {
local ft=$(file $1| awk -F" " '{print $2}')
local basedir=$(dirname $1)
@@ -166,7 +145,6 @@ do
tmpltimg="$OPTARG"
;;
s) sflag=1
- sflag=1
;;
c) cflag=1
snapshotName="$OPTARG"
diff --git a/scripts/storage/qcow2/createvolume.sh b/scripts/storage/qcow2/createvolume.sh
index 91a76323f15..033cc91b108 100755
--- a/scripts/storage/qcow2/createvolume.sh
+++ b/scripts/storage/qcow2/createvolume.sh
@@ -22,7 +22,7 @@
# createvol.sh -- install a volume
usage() {
- printf "Usage: %s: -t <volume-fs> -n <volumename> -f <root disk file> -s <size in Gigabytes> -c <md5 cksum> -d <descr> -h [-u]\n" $(basename $0) >&2
+ printf "Usage: %s: -t <volume-fs> -n <volumename> -f <root disk file> -s <size in Gigabytes> -c <snapshot name> -d <descr> -h [-u]\n" $(basename $0) >&2
}
@@ -38,27 +38,6 @@ then
fi
fi
-
-verify_cksum() {
- digestalgo=""
- case ${#1} in
- 32) digestalgo="md5sum" ;;
- 40) digestalgo="sha1sum" ;;
- 56) digestalgo="sha224sum" ;;
- 64) digestalgo="sha256sum" ;;
- 96) digestalgo="sha384sum" ;;
- 128) digestalgo="sha512sum" ;;
- *) echo "Please provide valid cheksum" ; exit 3 ;;
- esac
- echo "$1 $2" | $digestalgo -c --status
- #printf "$1\t$2" | $digestalgo -c --status
- if [ $? -gt 0 ]
- then
- printf "Checksum failed, not proceeding with install\n"
- exit 3
- fi
-}
-
untar() {
local ft=$(file $1| awk -F" " '{print $2}')
local basedir=$(dirname $1)
@@ -167,7 +146,6 @@ do
volimg="$OPTARG"
;;
s) sflag=1
- sflag=1
;;
c) cflag=1
snapshotName="$OPTARG"
diff --git a/scripts/storage/secondary/createtmplt.sh b/scripts/storage/secondary/createtmplt.sh
index acc4ef5c928..4e8db4633f0 100755
--- a/scripts/storage/secondary/createtmplt.sh
+++ b/scripts/storage/secondary/createtmplt.sh
@@ -22,7 +22,7 @@
# createtmplt.sh -- install a template
usage() {
- printf "Usage: %s: -t <template-fs> -n <templatename> -f <root disk file> -c <md5 cksum> -d <descr> -h [-u] [-v]\n" $(basename $0) >&2
+ printf "Usage: %s: -t <template-fs> -n <templatename> -f <root disk file> -d <descr> -h [-u] [-v]\n" $(basename $0) >&2
}
@@ -39,26 +39,6 @@ rollback_if_needed() {
fi
}
-verify_cksum() {
- digestalgo=""
- case ${#1} in
- 32) digestalgo="md5sum" ;;
- 40) digestalgo="sha1sum" ;;
- 56) digestalgo="sha224sum" ;;
- 64) digestalgo="sha256sum" ;;
- 96) digestalgo="sha384sum" ;;
- 128) digestalgo="sha512sum" ;;
- *) echo "Please provide valid cheksum" ; exit 3 ;;
- esac
- echo "$1 $2" | $digestalgo -c --status
- #printf "$1\t$2" | $digestalgo -c --status
- if [ $? -gt 0 ]
- then
- printf "Checksum failed, not proceeding with install\n"
- exit 3
- fi
-}
-
untar() {
local ft=$(file $1| awk -F" " '{print $2}')
case $ft in
@@ -138,9 +118,8 @@ hflag=
hvm=false
cleanup=false
dflag=
-cflag=
-while getopts 'vuht:n:f:s:c:d:S:' OPTION
+while getopts 'vuht:n:f:s:d:S:' OPTION
do
case $OPTION in
t) tflag=1
@@ -154,9 +133,6 @@ do
;;
s) sflag=1
;;
- c) cflag=1
- cksum="$OPTARG"
- ;;
d) dflag=1
descr="$OPTARG"
;;
@@ -200,10 +176,6 @@ then
exit 3
fi
-if [ -n "$cksum" ]
-then
- verify_cksum $cksum $tmpltimg
-fi
[ -n "$verbose" ] && is_compressed $tmpltimg
tmpltimg2=$(uncompress $tmpltimg)
rollback_if_needed $tmpltfs $? "failed to uncompress $tmpltimg\n"
@@ -236,6 +208,8 @@ echo -n "" > /$tmpltfs/template.properties
today=$(date '+%m_%d_%Y')
echo "filename=$tmpltname" > /$tmpltfs/template.properties
echo "description=$descr" >> /$tmpltfs/template.properties
+# we need to rethink this property as it might get changed after download due to decompression
+# option is to recalcutate it here
echo "checksum=$cksum" >> /$tmpltfs/template.properties
echo "hvm=$hvm" >> /$tmpltfs/template.properties
echo "size=$imgsize" >> /$tmpltfs/template.properties
diff --git a/scripts/storage/secondary/createvolume.sh b/scripts/storage/secondary/createvolume.sh
index c7836dcccb5..12f73ebc109 100755
--- a/scripts/storage/secondary/createvolume.sh
+++ b/scripts/storage/secondary/createvolume.sh
@@ -41,6 +41,7 @@ fi
verify_cksum() {
digestalgo=""
+# NOTE this will only work with 0-padded checksums
case ${#1} in
32) digestalgo="md5sum" ;;
40) digestalgo="sha1sum" ;;
diff --git a/scripts/util/keystore-cert-import b/scripts/util/keystore-cert-import
new file mode 100755
index 00000000000..bb03b6f68b4
--- /dev/null
+++ b/scripts/util/keystore-cert-import
@@ -0,0 +1,100 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+PROPS_FILE="$1"
+KS_FILE="$2"
+MODE="$3"
+CERT_FILE="$4"
+CERT=$(echo "$5" | tr '^' '\n' | tr '~' ' ')
+CACERT_FILE="$6"
+CACERT=$(echo "$7" | tr '^' '\n' | tr '~' ' ')
+PRIVKEY_FILE="$8"
+PRIVKEY=$(echo "$9" | tr '^' '\n' | tr '~' ' ')
+
+ALIAS="cloud"
+SYSTEM_FILE="/var/cache/cloud/cmdline"
+
+# Find keystore password
+KS_PASS=$(sed -n '/keystore.passphrase/p' "$PROPS_FILE" 2>/dev/null | sed 's/keystore.passphrase=//g' 2>/dev/null)
+
+if [ -z "${KS_PASS// }" ]; then
+ echo "Failed to find keystore passphrase from file: $PROPS_FILE, quiting!"
+ exit 1
+fi
+
+# Use a new keystore file
+NEW_KS_FILE="$KS_FILE.new"
+
+# Import certificate
+if [ ! -z "${CERT// }" ]; then
+ echo "$CERT" > "$CERT_FILE"
+fi
+
+# Import ca certs
+if [ ! -z "${CACERT// }" ]; then
+ echo "$CACERT" > "$CACERT_FILE"
+fi
+
+# Import cacerts into the keystore
+awk '/-----BEGIN CERTIFICATE-----?/{n++}{print > "cloudca." n }' "$CACERT_FILE"
+for caChain in $(ls cloudca.*); do
+ keytool -delete -noprompt -alias "$caChain" -keystore "$NEW_KS_FILE" -storepass "$KS_PASS" > /dev/null 2>&1 || true
+ keytool -import -noprompt -storepass "$KS_PASS" -trustcacerts -alias "$caChain" -file "$caChain" -keystore "$NEW_KS_FILE" > /dev/null 2>&1
+done
+rm -f cloudca.*
+
+# Import private key if available
+if [ ! -z "${PRIVKEY// }" ]; then
+ echo "$PRIVKEY" > "$PRIVKEY_FILE"
+ # Re-initialize keystore when private key is provided
+ keytool -delete -noprompt -alias "$ALIAS" -keystore "$NEW_KS_FILE" -storepass "$KS_PASS" 2>/dev/null || true
+ openssl pkcs12 -export -name "$ALIAS" -in "$CERT_FILE" -inkey "$PRIVKEY_FILE" -out "$NEW_KS_FILE.p12" -password pass:"$KS_PASS" > /dev/null 2>&1
+ keytool -importkeystore -srckeystore "$NEW_KS_FILE.p12" -destkeystore "$NEW_KS_FILE" -srcstoretype PKCS12 -alias "$ALIAS" -deststorepass "$KS_PASS" -destkeypass "$KS_PASS" -srcstorepass "$KS_PASS" -srckeypass "$KS_PASS" > /dev/null 2>&1
+else
+ # Import certificate into the keystore
+ keytool -import -storepass "$KS_PASS" -alias "$ALIAS" -file "$CERT_FILE" -keystore "$NEW_KS_FILE" > /dev/null 2>&1 || true
+ # Export private key from keystore
+ rm -f "$PRIVKEY_FILE"
+ keytool -importkeystore -srckeystore "$NEW_KS_FILE" -destkeystore "$NEW_KS_FILE.p12" -deststoretype PKCS12 -srcalias "$ALIAS" -deststorepass "$KS_PASS" -destkeypass "$KS_PASS" -srcstorepass "$KS_PASS" -srckeypass "$KS_PASS" > /dev/null 2>&1
+ openssl pkcs12 -in "$NEW_KS_FILE.p12" -nodes -nocerts -nomac -password pass:"$KS_PASS" 2>/dev/null | openssl rsa -out "$PRIVKEY_FILE" > /dev/null 2>&1
+fi
+
+# Commit the new keystore
+rm -f "$NEW_KS_FILE.p12"
+mv -f "$NEW_KS_FILE" "$KS_FILE"
+
+# Update ca-certs if we're in systemvm
+if [ -f "$SYSTEM_FILE" ]; then
+ mkdir -p /usr/local/share/ca-certificates/cloudstack
+ cp "$CACERT_FILE" /usr/local/share/ca-certificates/cloudstack/ca.crt
+ chmod 755 /usr/local/share/ca-certificates/cloudstack
+ chmod 644 /usr/local/share/ca-certificates/cloudstack/ca.crt
+ update-ca-certificates > /dev/null 2>&1 || true
+fi
+
+# Restart cloud service if we're in systemvm
+if [ "$MODE" == "ssh" ] && [ -f $SYSTEM_FILE ]; then
+ /etc/init.d/cloud stop > /dev/null 2>&1
+ sleep 2
+ /etc/init.d/cloud start > /dev/null 2>&1
+fi
+
+# Fix file permission
+chmod 600 $CACERT_FILE
+chmod 600 $CERT_FILE
+chmod 600 $PRIVKEY_FILE
diff --git a/scripts/util/keystore-setup b/scripts/util/keystore-setup
new file mode 100755
index 00000000000..28ce61c846a
--- /dev/null
+++ b/scripts/util/keystore-setup
@@ -0,0 +1,51 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+PROPS_FILE="$1"
+KS_FILE="$2.new"
+KS_PASS="$3"
+KS_VALIDITY="$4"
+CSR_FILE="$5"
+
+ALIAS="cloud"
+
+# Re-use existing password or use the one provided
+if [ -f "$PROPS_FILE" ]; then
+ OLD_PASS=$(sed -n '/keystore.passphrase/p' "$PROPS_FILE" 2>/dev/null | sed 's/keystore.passphrase=//g' 2>/dev/null)
+ if [ ! -z "${OLD_PASS// }" ]; then
+ KS_PASS="$OLD_PASS"
+ else
+ sed -i "/keystore.passphrase.*/d" $PROPS_FILE 2> /dev/null || true
+ echo "keystore.passphrase=$KS_PASS" >> $PROPS_FILE
+ fi
+fi
+
+# Generate keystore
+rm -f "$KS_FILE"
+CN=$(hostname --fqdn)
+keytool -genkey -storepass "$KS_PASS" -keypass "$KS_PASS" -alias "$ALIAS" -keyalg RSA -validity "$KS_VALIDITY" -dname cn="$CN",ou="cloudstack",o="cloudstack",c="cloudstack" -keystore "$KS_FILE"
+
+# Generate CSR
+rm -f "$CSR_FILE"
+keytool -certreq -storepass "$KS_PASS" -alias "$ALIAS" -file $CSR_FILE -keystore "$KS_FILE"
+cat "$CSR_FILE"
+
+# Fix file permissions
+chmod 600 $KS_FILE
+chmod 600 $PROPS_FILE
+chmod 600 $CSR_FILE
diff --git a/scripts/vm/hypervisor/kvm/kvmvmactivity.sh b/scripts/vm/hypervisor/kvm/kvmvmactivity.sh
new file mode 100755
index 00000000000..88ee8f380bb
--- /dev/null
+++ b/scripts/vm/hypervisor/kvm/kvmvmactivity.sh
@@ -0,0 +1,135 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+help() {
+ printf "Usage: $0
+ -i nfs server ip
+ -p nfs server path
+ -m mount point
+ -h host
+ -u volume uuid list
+ -t time on ms
+ -d suspect time\n"
+ exit 1
+}
+
+#set -x
+
+NfsSvrIP=
+NfsSvrPath=
+MountPoint=
+HostIP=
+UUIDList=
+MSTime=
+SuspectTime=
+
+while getopts 'i:p:m:u:t:h:d:' OPTION
+do
+ case $OPTION in
+ i)
+ NfsSvrIP="$OPTARG"
+ ;;
+ p)
+ NfsSvrPath="$OPTARG"
+ ;;
+ m)
+ MountPoint="$OPTARG"
+ ;;
+ h)
+ HostIP="$OPTARG"
+ ;;
+ u)
+ UUIDList="$OPTARG"
+ ;;
+ t)
+ MSTime="$OPTARG"
+ ;;
+ d)
+ SuspectTime="$OPTARG"
+ ;;
+ *)
+ help
+ ;;
+ esac
+done
+
+if [ -z "$NfsSvrIP" ]
+then
+ exit 2
+fi
+
+if [ -z "$SuspectTime" ]
+then
+ exit 2
+fi
+
+hbFile="$MountPoint/KVMHA/hb-$HostIP"
+acFile="$MountPoint/KVMHA/ac-$HostIP"
+
+# First check: heartbeat file
+now=$(date +%s)
+hb=$(cat $hbFile)
+diff=$(expr $now - $hb)
+if [ $diff -lt 61 ]
+then
+ echo "=====> ALIVE <====="
+ exit 0
+fi
+
+if [ -z "$UUIDList" ]
+then
+ echo "=====> DEAD <======"
+ exit 0
+fi
+
+# Second check: disk activity check
+cd $MountPoint
+latestUpdateTime=$(stat -c %Y $(echo $UUIDList | sed 's/,/ /g') | sort -nr | head -1)
+
+if [ ! -f $acFile ]; then
+ echo "$SuspectTime:$latestUpdateTime:$MSTime" > $acFile
+
+ if [[ $latestUpdateTime -gt $SuspectTime ]]; then
+ echo "=====> ALIVE <====="
+ else
+ echo "=====> DEAD <======"
+ fi
+else
+ acTime=$(cat $acFile)
+ arrTime=(${acTime//:/ })
+ lastSuspectTime=${arrTime[0]}
+ lastUpdateTime=${arrTime[1]}
+ echo "$SuspectTime:$latestUpdateTime:$MSTime" > $acFile
+
+ suspectTimeDiff=$(expr $SuspectTime - $lastSuspectTime)
+ if [[ $suspectTimeDiff -lt 0 ]]; then
+ if [[ $latestUpdateTime -gt $SuspectTime ]]; then
+ echo "=====> ALIVE <====="
+ else
+ echo "=====> DEAD <======"
+ fi
+ else
+ if [[ $latestUpdateTime -gt $lastUpdateTime ]]; then
+ echo "=====> ALIVE <====="
+ else
+ echo "=====> DEAD <======"
+ fi
+ fi
+fi
+
+exit 0
diff --git a/packaging/fedora20/cloudstack-sccs b/scripts/vm/hypervisor/xenserver/logrotate
similarity index 68%
rename from packaging/fedora20/cloudstack-sccs
rename to scripts/vm/hypervisor/xenserver/logrotate
index e05d372c7fe..375b7e700e3 100644
--- a/packaging/fedora20/cloudstack-sccs
+++ b/scripts/vm/hypervisor/xenserver/logrotate
@@ -1,5 +1,4 @@
-#!/bin/sh
-
+#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
@@ -17,4 +16,14 @@
# specific language governing permissions and limitations
# under the License.
-cat /usr/share/cloudstack-common/scripts/gitrev.txt
+# Version @VERSION@
+#
+# script to perform logrotation on xenserver 6.0.2 and later
+
+/usr/sbin/logrotate /etc/logrotate.d/cloudlog
+EXITVALUE=$?
+if [ $EXITVALUE != 0 ]; then
+/usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
+fi
+[ -f /opt/xensource/bin/delete_old_logs_by_space ] && /opt/xensource/bin/delete_old_logs_by_space
+exit 0
diff --git a/scripts/vm/hypervisor/xenserver/setupxenserver.sh b/scripts/vm/hypervisor/xenserver/setupxenserver.sh
index 14ba1c28c90..6c850c6665e 100755
--- a/scripts/vm/hypervisor/xenserver/setupxenserver.sh
+++ b/scripts/vm/hypervisor/xenserver/setupxenserver.sh
@@ -49,7 +49,7 @@ sed -i 's/0\.0\.0\.0/127\.0\.0\.1/' /opt/xensource/libexec/qemu-dm-wrapper 2>&1
sed -i /NOZEROCONF/d /etc/sysconfig/network
echo "NOZEROCONF=yes" >> /etc/sysconfig/network
-mv -n /etc/cron.daily/logrotate /etc/cron.hourly 2>&1
+[ -f /etc/cron.hourly/logrotate ] || mv /etc/cron.daily/logrotate /etc/cron.hourly 2>&1
# more aio thread
echo 1048576 >/proc/sys/fs/aio-max-nr
diff --git a/scripts/vm/hypervisor/xenserver/xenserver60/patch b/scripts/vm/hypervisor/xenserver/xenserver60/patch
index 4b0973f918d..bea0cf9bfd1 100644
--- a/scripts/vm/hypervisor/xenserver/xenserver60/patch
+++ b/scripts/vm/hypervisor/xenserver/xenserver60/patch
@@ -69,3 +69,4 @@ ovs-get-dhcp-iface.sh=..,0755,/opt/cloud/bin
ovs-get-bridge.sh=..,0755,/opt/cloud/bin
cloudlog=..,0644,/etc/logrotate.d
update_host_passwd.sh=../..,0755,/opt/cloud/bin
+logrotate=..,0755,/etc/cron.hourly
\ No newline at end of file
diff --git a/scripts/vm/hypervisor/xenserver/xenserver62/patch b/scripts/vm/hypervisor/xenserver/xenserver62/patch
index 8f65877da8c..db137c9826f 100644
--- a/scripts/vm/hypervisor/xenserver/xenserver62/patch
+++ b/scripts/vm/hypervisor/xenserver/xenserver62/patch
@@ -65,3 +65,4 @@ ovs-get-dhcp-iface.sh=..,0755,/opt/cloud/bin
ovs-get-bridge.sh=..,0755,/opt/cloud/bin
cloudlog=..,0644,/etc/logrotate.d
update_host_passwd.sh=../..,0755,/opt/cloud/bin
+logrotate=..,0755,/etc/cron.hourly
\ No newline at end of file
diff --git a/scripts/vm/hypervisor/xenserver/xenserver65/patch b/scripts/vm/hypervisor/xenserver/xenserver65/patch
index 8f65877da8c..db137c9826f 100644
--- a/scripts/vm/hypervisor/xenserver/xenserver65/patch
+++ b/scripts/vm/hypervisor/xenserver/xenserver65/patch
@@ -65,3 +65,4 @@ ovs-get-dhcp-iface.sh=..,0755,/opt/cloud/bin
ovs-get-bridge.sh=..,0755,/opt/cloud/bin
cloudlog=..,0644,/etc/logrotate.d
update_host_passwd.sh=../..,0755,/opt/cloud/bin
+logrotate=..,0755,/etc/cron.hourly
\ No newline at end of file
diff --git a/scripts/vm/network/security_group.py b/scripts/vm/network/security_group.py
index d95e35ddfad..9e3eeb062bb 100755
--- a/scripts/vm/network/security_group.py
+++ b/scripts/vm/network/security_group.py
@@ -1052,7 +1052,11 @@ def add_network_rules(vm_name, vm_id, vm_ip, vm_ip6, signature, seqno, vmMac, ru
elif 'icmp' != protocol:
execute('ip6tables -I ' + vmchain + ' -p ' + protocol + ' -m ' + protocol + ' --dport ' + range + ' -m state --state NEW ' + direction + ' ' + ip + ' -j ' + action)
else:
- execute('ip6tables -I ' + vmchain + ' -p icmpv6 --icmpv6-type ' + range + ' ' + direction + ' ' + ip + ' -j ' + action)
+ # ip6tables does not allow '--icmpv6-type any', allowing all ICMPv6 is done by not allowing a specific type
+ if range == 'any':
+ execute('ip6tables -I ' + vmchain + ' -p icmpv6 ' + direction + ' ' + ip + ' -j ' + action)
+ else:
+ execute('ip6tables -I ' + vmchain + ' -p icmpv6 --icmpv6-type ' + range + ' ' + direction + ' ' + ip + ' -j ' + action)
egress_vmchain = egress_chain_name(vm_name)
if egressrule_v4 == 0 :
diff --git a/server/pom.xml b/server/pom.xml
index 90ddeb1cf00..4067b8590a0 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -15,7 +15,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
@@ -52,6 +52,11 @@
<artifactId>httpcore</artifactId>
<version>${cs.httpcore.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-framework-ca</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-framework-jobs</artifactId>
diff --git a/server/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml b/server/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml
index 87097a4e048..94e8559120a 100644
--- a/server/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml
+++ b/server/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml
@@ -70,6 +70,15 @@
value="#{resourceDiscoverersRegistry.registered}" />
</bean>
+ <!-- the new background poll manager -->
+ <bean id="bgPollManager" class="org.apache.cloudstack.poll.BackgroundPollManagerImpl">
+ </bean>
+
+ <!-- the new HA manager -->
+ <bean id="haManagerImpl" class="org.apache.cloudstack.ha.HAManagerImpl">
+ <property name="haProviders" value="#{haProvidersRegistry.registered}" />
+ </bean>
+
<bean id="highAvailabilityManagerExtImpl" class="com.cloud.ha.HighAvailabilityManagerExtImpl">
<property name="investigators" value="#{haInvestigatorsRegistry.registered}" />
<property name="fenceBuilders" value="#{haFenceBuildersRegistry.registered}" />
@@ -83,8 +92,10 @@
<property name="networkElements" value="#{networkElementsRegistry.registered}" />
</bean>
+
<bean id="configurationServerImpl" class="com.cloud.server.ConfigurationServerImpl" />
+
<bean id="userVmManagerImpl" class="com.cloud.vm.UserVmManagerImpl" />
<bean id="consoleProxyManagerImpl" class="com.cloud.consoleproxy.ConsoleProxyManagerImpl">
@@ -272,5 +283,14 @@
<property name="gslbServiceProviders" value="#{gslbServiceProvidersRegistry.registered}" />
</bean>
<bean id="certServiceImpl" class="org.apache.cloudstack.network.ssl.CertServiceImpl" />
+
<bean id="imageStoreUploadMonitorImpl" class="com.cloud.storage.ImageStoreUploadMonitorImpl" />
+
+ <!-- the new CA manager -->
+ <bean id="caManager" class="org.apache.cloudstack.ca.CAManagerImpl">
+ <property name="caProviders" value="#{caProvidersRegistry.registered}" />
+ </bean>
+
+ <bean id="annotationService" class="org.apache.cloudstack.annotation.AnnotationManagerImpl" />
+
</beans>
diff --git a/server/src/com/cloud/alert/AlertManagerImpl.java b/server/src/com/cloud/alert/AlertManagerImpl.java
index e18d231e173..a58a4f8b0f9 100644
--- a/server/src/com/cloud/alert/AlertManagerImpl.java
+++ b/server/src/com/cloud/alert/AlertManagerImpl.java
@@ -90,7 +90,7 @@
private static final Logger s_logger = Logger.getLogger(AlertManagerImpl.class.getName());
private static final Logger s_alertsLogger = Logger.getLogger("org.apache.cloudstack.alerts");
- private static final long INITIAL_CAPACITY_CHECK_DELAY = 30L * 1000L; // thirty seconds expressed in milliseconds
+ private static final long INITIAL_CAPACITY_CHECK_DELAY = 30L * 1000L; // Thirty seconds expressed in milliseconds.
private static final DecimalFormat DfPct = new DecimalFormat("###.##");
private static final DecimalFormat DfWhole = new DecimalFormat("########");
@@ -126,7 +126,7 @@
protected ConfigDepot _configDepot;
private Timer _timer = null;
- private long _capacityCheckPeriod = 60L * 60L * 1000L; // one hour by default
+ private long _capacityCheckPeriod = 60L * 60L * 1000L; // One hour by default.
private double _publicIPCapacityThreshold = 0.75;
private double _privateIPCapacityThreshold = 0.75;
private double _secondaryStorageCapacityThreshold = 0.75;
@@ -249,8 +249,8 @@ public void sendAlert(AlertType alertType, long dataCenterId, Long podId, String
if (_emailAlert != null) {
_emailAlert.sendAlert(alertType, dataCenterId, podId, null, subject, body);
} else {
- s_alertsLogger.warn(" alertType:: " + alertType + " // dataCenterId:: " + dataCenterId + " // podId:: " + podId +
- " // message:: " + subject + " // body:: " + body);
+ s_alertsLogger.warn("AlertType:: " + alertType + " | dataCenterId:: " + dataCenterId + " | podId:: " + podId +
+ " | message:: " + subject + " | body:: " + body);
}
} catch (Exception ex) {
s_logger.error("Problem sending email alert", ex);
@@ -367,7 +367,8 @@ private void createOrUpdateVlanCapacity(long dcId, AllocationState capacityState
CapacityVO newVlanCapacity = new CapacityVO(null, dcId, null, null, allocatedVlans, totalVlans, Capacity.CAPACITY_TYPE_VLAN);
newVlanCapacity.setCapacityState(vlanCapacityState);
_capacityDao.persist(newVlanCapacity);
- } else if (!(capacities.get(0).getUsedCapacity() == allocatedVlans && capacities.get(0).getTotalCapacity() == totalVlans && capacities.get(0).getCapacityState() == vlanCapacityState)) {
+ } else if (!(capacities.get(0).getUsedCapacity() == allocatedVlans && capacities.get(0).getTotalCapacity() == totalVlans
+ && capacities.get(0).getCapacityState() == vlanCapacityState)) {
CapacityVO capacity = capacities.get(0);
capacity.setUsedCapacity(allocatedVlans);
capacity.setTotalCapacity(totalVlans);
@@ -405,7 +406,8 @@ public void createOrUpdateIpCapacity(Long dcId, Long podId, short capacityType,
CapacityVO newPublicIPCapacity = new CapacityVO(null, dcId, podId, null, allocatedIPs, totalIPs, capacityType);
newPublicIPCapacity.setCapacityState(ipCapacityState);
_capacityDao.persist(newPublicIPCapacity);
- } else if (!(capacities.get(0).getUsedCapacity() == allocatedIPs && capacities.get(0).getTotalCapacity() == totalIPs && capacities.get(0).getCapacityState() == ipCapacityState)) {
+ } else if (!(capacities.get(0).getUsedCapacity() == allocatedIPs && capacities.get(0).getTotalCapacity() == totalIPs
+ && capacities.get(0).getCapacityState() == ipCapacityState)) {
CapacityVO capacity = capacities.get(0);
capacity.setUsedCapacity(allocatedIPs);
capacity.setTotalCapacity(totalIPs);
@@ -489,21 +491,21 @@ public void checkForAlerts() {
// cpu and memory allocated capacity notification threshold can be defined at cluster level, so getting the value if they are defined at cluster level
double threshold = 0;
switch (capacityType) {
- case Capacity.CAPACITY_TYPE_STORAGE:
- capacity.add(getUsedStats(capacityType, cluster.getDataCenterId(), cluster.getPodId(), cluster.getId()));
- threshold = StorageCapacityThreshold.valueIn(cluster.getId());
- break;
- case Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED:
- threshold = StorageAllocatedCapacityThreshold.valueIn(cluster.getId());
- break;
- case Capacity.CAPACITY_TYPE_CPU:
- threshold = CPUCapacityThreshold.valueIn(cluster.getId());
- break;
- case Capacity.CAPACITY_TYPE_MEMORY:
- threshold = MemoryCapacityThreshold.valueIn(cluster.getId());
- break;
- default:
- threshold = _capacityTypeThresholdMap.get(capacityType);
+ case Capacity.CAPACITY_TYPE_STORAGE:
+ capacity.add(getUsedStats(capacityType, cluster.getDataCenterId(), cluster.getPodId(), cluster.getId()));
+ threshold = StorageCapacityThreshold.valueIn(cluster.getId());
+ break;
+ case Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED:
+ threshold = StorageAllocatedCapacityThreshold.valueIn(cluster.getId());
+ break;
+ case Capacity.CAPACITY_TYPE_CPU:
+ threshold = CPUCapacityThreshold.valueIn(cluster.getId());
+ break;
+ case Capacity.CAPACITY_TYPE_MEMORY:
+ threshold = MemoryCapacityThreshold.valueIn(cluster.getId());
+ break;
+ default:
+ threshold = _capacityTypeThresholdMap.get(capacityType);
}
if (capacity == null || capacity.size() == 0) {
continue;
@@ -513,7 +515,7 @@ public void checkForAlerts() {
double usedCapacity = capacity.get(0).getUsedCapacity() + capacity.get(0).getReservedCapacity();
if (totalCapacity != 0 && usedCapacity / totalCapacity > threshold) {
generateEmailAlert(ApiDBUtils.findZoneById(cluster.getDataCenterId()), ApiDBUtils.findPodById(cluster.getPodId()), cluster, totalCapacity,
- usedCapacity, capacityType);
+ usedCapacity, capacityType);
}
}
}
@@ -549,84 +551,82 @@ private void generateEmailAlert(DataCenterVO dc, HostPodVO pod, ClusterVO cluste
switch (capacityType) {
//Cluster Level
- case Capacity.CAPACITY_TYPE_MEMORY:
- msgSubject = "System Alert: Low Available Memory in cluster " + cluster.getName() + " pod " + pod.getName() + " of availability zone " + dc.getName();
- totalStr = formatBytesToMegabytes(totalCapacity);
- usedStr = formatBytesToMegabytes(usedCapacity);
- msgContent = "System memory is low, total: " + totalStr + " MB, used: " + usedStr + " MB (" + pctStr + "%)";
- alertType = AlertManager.AlertType.ALERT_TYPE_MEMORY;
- break;
- case Capacity.CAPACITY_TYPE_CPU:
- msgSubject = "System Alert: Low Unallocated CPU in cluster " + cluster.getName() + " pod " + pod.getName() + " of availability zone " + dc.getName();
- totalStr = DfWhole.format(totalCapacity);
- usedStr = DfWhole.format(usedCapacity);
- msgContent = "Unallocated CPU is low, total: " + totalStr + " Mhz, used: " + usedStr + " Mhz (" + pctStr + "%)";
- alertType = AlertManager.AlertType.ALERT_TYPE_CPU;
- break;
- case Capacity.CAPACITY_TYPE_STORAGE:
- msgSubject = "System Alert: Low Available Storage in cluster " + cluster.getName() + " pod " + pod.getName() + " of availability zone " + dc.getName();
- totalStr = formatBytesToMegabytes(totalCapacity);
- usedStr = formatBytesToMegabytes(usedCapacity);
- msgContent = "Available storage space is low, total: " + totalStr + " MB, used: " + usedStr + " MB (" + pctStr + "%)";
- alertType = AlertManager.AlertType.ALERT_TYPE_STORAGE;
- break;
- case Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED:
- msgSubject =
- "System Alert: Remaining unallocated Storage is low in cluster " + cluster.getName() + " pod " + pod.getName() + " of availability zone " +
- dc.getName();
- totalStr = formatBytesToMegabytes(totalCapacity);
- usedStr = formatBytesToMegabytes(usedCapacity);
- msgContent = "Unallocated storage space is low, total: " + totalStr + " MB, allocated: " + usedStr + " MB (" + pctStr + "%)";
- alertType = AlertManager.AlertType.ALERT_TYPE_STORAGE_ALLOCATED;
- break;
- case Capacity.CAPACITY_TYPE_LOCAL_STORAGE:
- msgSubject =
- "System Alert: Remaining unallocated Local Storage is low in cluster " + cluster.getName() + " pod " + pod.getName() + " of availability zone " +
- dc.getName();
- totalStr = formatBytesToMegabytes(totalCapacity);
- usedStr = formatBytesToMegabytes(usedCapacity);
- msgContent = "Unallocated storage space is low, total: " + totalStr + " MB, allocated: " + usedStr + " MB (" + pctStr + "%)";
- alertType = AlertManager.AlertType.ALERT_TYPE_LOCAL_STORAGE;
- break;
-
- //Pod Level
- case Capacity.CAPACITY_TYPE_PRIVATE_IP:
- msgSubject = "System Alert: Number of unallocated private IPs is low in pod " + pod.getName() + " of availability zone " + dc.getName();
- totalStr = Double.toString(totalCapacity);
- usedStr = Double.toString(usedCapacity);
- msgContent = "Number of unallocated private IPs is low, total: " + totalStr + ", allocated: " + usedStr + " (" + pctStr + "%)";
- alertType = AlertManager.AlertType.ALERT_TYPE_PRIVATE_IP;
- break;
-
- //Zone Level
- case Capacity.CAPACITY_TYPE_SECONDARY_STORAGE:
- msgSubject = "System Alert: Low Available Secondary Storage in availability zone " + dc.getName();
- totalStr = formatBytesToMegabytes(totalCapacity);
- usedStr = formatBytesToMegabytes(usedCapacity);
- msgContent = "Available secondary storage space is low, total: " + totalStr + " MB, used: " + usedStr + " MB (" + pctStr + "%)";
- alertType = AlertManager.AlertType.ALERT_TYPE_SECONDARY_STORAGE;
- break;
- case Capacity.CAPACITY_TYPE_VIRTUAL_NETWORK_PUBLIC_IP:
- msgSubject = "System Alert: Number of unallocated virtual network public IPs is low in availability zone " + dc.getName();
- totalStr = Double.toString(totalCapacity);
- usedStr = Double.toString(usedCapacity);
- msgContent = "Number of unallocated public IPs is low, total: " + totalStr + ", allocated: " + usedStr + " (" + pctStr + "%)";
- alertType = AlertManager.AlertType.ALERT_TYPE_VIRTUAL_NETWORK_PUBLIC_IP;
- break;
- case Capacity.CAPACITY_TYPE_DIRECT_ATTACHED_PUBLIC_IP:
- msgSubject = "System Alert: Number of unallocated shared network IPs is low in availability zone " + dc.getName();
- totalStr = Double.toString(totalCapacity);
- usedStr = Double.toString(usedCapacity);
- msgContent = "Number of unallocated shared network IPs is low, total: " + totalStr + ", allocated: " + usedStr + " (" + pctStr + "%)";
- alertType = AlertManager.AlertType.ALERT_TYPE_DIRECT_ATTACHED_PUBLIC_IP;
- break;
- case Capacity.CAPACITY_TYPE_VLAN:
- msgSubject = "System Alert: Number of unallocated VLANs is low in availability zone " + dc.getName();
- totalStr = Double.toString(totalCapacity);
- usedStr = Double.toString(usedCapacity);
- msgContent = "Number of unallocated VLANs is low, total: " + totalStr + ", allocated: " + usedStr + " (" + pctStr + "%)";
- alertType = AlertManager.AlertType.ALERT_TYPE_VLAN;
- break;
+ case Capacity.CAPACITY_TYPE_MEMORY:
+ msgSubject = "System Alert: Low Available Memory in cluster " + cluster.getName() + " pod " + pod.getName() + " of availability zone " + dc.getName();
+ totalStr = formatBytesToMegabytes(totalCapacity);
+ usedStr = formatBytesToMegabytes(usedCapacity);
+ msgContent = "System memory is low, total: " + totalStr + " MB, used: " + usedStr + " MB (" + pctStr + "%)";
+ alertType = AlertManager.AlertType.ALERT_TYPE_MEMORY;
+ break;
+ case Capacity.CAPACITY_TYPE_CPU:
+ msgSubject = "System Alert: Low Unallocated CPU in cluster " + cluster.getName() + " pod " + pod.getName() + " of availability zone " + dc.getName();
+ totalStr = DfWhole.format(totalCapacity);
+ usedStr = DfWhole.format(usedCapacity);
+ msgContent = "Unallocated CPU is low, total: " + totalStr + " Mhz, used: " + usedStr + " Mhz (" + pctStr + "%)";
+ alertType = AlertManager.AlertType.ALERT_TYPE_CPU;
+ break;
+ case Capacity.CAPACITY_TYPE_STORAGE:
+ msgSubject = "System Alert: Low Available Storage in cluster " + cluster.getName() + " pod " + pod.getName() + " of availability zone " + dc.getName();
+ totalStr = formatBytesToMegabytes(totalCapacity);
+ usedStr = formatBytesToMegabytes(usedCapacity);
+ msgContent = "Available storage space is low, total: " + totalStr + " MB, used: " + usedStr + " MB (" + pctStr + "%)";
+ alertType = AlertManager.AlertType.ALERT_TYPE_STORAGE;
+ break;
+ case Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED:
+ msgSubject = "System Alert: Remaining unallocated Storage is low in cluster " + cluster.getName() + " pod " + pod.getName() + " of availability zone " +
+ dc.getName();
+ totalStr = formatBytesToMegabytes(totalCapacity);
+ usedStr = formatBytesToMegabytes(usedCapacity);
+ msgContent = "Unallocated storage space is low, total: " + totalStr + " MB, allocated: " + usedStr + " MB (" + pctStr + "%)";
+ alertType = AlertManager.AlertType.ALERT_TYPE_STORAGE_ALLOCATED;
+ break;
+ case Capacity.CAPACITY_TYPE_LOCAL_STORAGE:
+ msgSubject = "System Alert: Remaining unallocated Local Storage is low in cluster " + cluster.getName() + " pod " + pod.getName() + " of availability zone " +
+ dc.getName();
+ totalStr = formatBytesToMegabytes(totalCapacity);
+ usedStr = formatBytesToMegabytes(usedCapacity);
+ msgContent = "Unallocated storage space is low, total: " + totalStr + " MB, allocated: " + usedStr + " MB (" + pctStr + "%)";
+ alertType = AlertManager.AlertType.ALERT_TYPE_LOCAL_STORAGE;
+ break;
+
+ //Pod Level
+ case Capacity.CAPACITY_TYPE_PRIVATE_IP:
+ msgSubject = "System Alert: Number of unallocated private IPs is low in pod " + pod.getName() + " of availability zone " + dc.getName();
+ totalStr = Double.toString(totalCapacity);
+ usedStr = Double.toString(usedCapacity);
+ msgContent = "Number of unallocated private IPs is low, total: " + totalStr + ", allocated: " + usedStr + " (" + pctStr + "%)";
+ alertType = AlertManager.AlertType.ALERT_TYPE_PRIVATE_IP;
+ break;
+
+ //Zone Level
+ case Capacity.CAPACITY_TYPE_SECONDARY_STORAGE:
+ msgSubject = "System Alert: Low Available Secondary Storage in availability zone " + dc.getName();
+ totalStr = formatBytesToMegabytes(totalCapacity);
+ usedStr = formatBytesToMegabytes(usedCapacity);
+ msgContent = "Available secondary storage space is low, total: " + totalStr + " MB, used: " + usedStr + " MB (" + pctStr + "%)";
+ alertType = AlertManager.AlertType.ALERT_TYPE_SECONDARY_STORAGE;
+ break;
+ case Capacity.CAPACITY_TYPE_VIRTUAL_NETWORK_PUBLIC_IP:
+ msgSubject = "System Alert: Number of unallocated virtual network public IPs is low in availability zone " + dc.getName();
+ totalStr = Double.toString(totalCapacity);
+ usedStr = Double.toString(usedCapacity);
+ msgContent = "Number of unallocated public IPs is low, total: " + totalStr + ", allocated: " + usedStr + " (" + pctStr + "%)";
+ alertType = AlertManager.AlertType.ALERT_TYPE_VIRTUAL_NETWORK_PUBLIC_IP;
+ break;
+ case Capacity.CAPACITY_TYPE_DIRECT_ATTACHED_PUBLIC_IP:
+ msgSubject = "System Alert: Number of unallocated shared network IPs is low in availability zone " + dc.getName();
+ totalStr = Double.toString(totalCapacity);
+ usedStr = Double.toString(usedCapacity);
+ msgContent = "Number of unallocated shared network IPs is low, total: " + totalStr + ", allocated: " + usedStr + " (" + pctStr + "%)";
+ alertType = AlertManager.AlertType.ALERT_TYPE_DIRECT_ATTACHED_PUBLIC_IP;
+ break;
+ case Capacity.CAPACITY_TYPE_VLAN:
+ msgSubject = "System Alert: Number of unallocated VLANs is low in availability zone " + dc.getName();
+ totalStr = Double.toString(totalCapacity);
+ usedStr = Double.toString(usedCapacity);
+ msgContent = "Number of unallocated VLANs is low, total: " + totalStr + ", allocated: " + usedStr + " (" + pctStr + "%)";
+ alertType = AlertManager.AlertType.ALERT_TYPE_VLAN;
+ break;
}
try {
@@ -746,9 +746,9 @@ protected PasswordAuthentication getPasswordAuthentication() {
// TODO: make sure this handles SSL transport (useAuth is true) and regular
public void sendAlert(AlertType alertType, long dataCenterId, Long podId, Long clusterId, String subject, String content) throws MessagingException,
- UnsupportedEncodingException {
- s_alertsLogger.warn(" alertType:: " + alertType + " // dataCenterId:: " + dataCenterId + " // podId:: " +
- podId + " // clusterId:: " + clusterId + " // message:: " + subject);
+ UnsupportedEncodingException {
+ s_alertsLogger.warn("AlertType:: " + alertType + " | dataCenterId:: " + dataCenterId + " | podId:: " +
+ podId + " | clusterId:: " + clusterId + " | message:: " + subject);
AlertVO alert = null;
if ((alertType != AlertManager.AlertType.ALERT_TYPE_HOST) &&
(alertType != AlertManager.AlertType.ALERT_TYPE_USERVM) &&
@@ -759,7 +759,9 @@ public void sendAlert(AlertType alertType, long dataCenterId, Long podId, Long c
(alertType != AlertManager.AlertType.ALERT_TYPE_MANAGMENT_NODE) &&
(alertType != AlertManager.AlertType.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED) &&
(alertType != AlertManager.AlertType.ALERT_TYPE_UPLOAD_FAILED) &&
- (alertType != AlertManager.AlertType.ALERT_TYPE_OOBM_AUTH_ERROR)) {
+ (alertType != AlertManager.AlertType.ALERT_TYPE_OOBM_AUTH_ERROR) &&
+ (alertType != AlertManager.AlertType.ALERT_TYPE_HA_ACTION) &&
+ (alertType != AlertManager.AlertType.ALERT_TYPE_CA_CERT)) {
alert = _alertDao.getLastAlert(alertType.getType(), dataCenterId, podId, clusterId);
}
@@ -771,7 +773,7 @@ public void sendAlert(AlertType alertType, long dataCenterId, Long podId, Long c
newAlert.setClusterId(clusterId);
newAlert.setPodId(podId);
newAlert.setDataCenterId(dataCenterId);
- newAlert.setSentCount(1); // initialize sent count to 1 since we are now sending an alert
+ newAlert.setSentCount(1); // Initialize sent count to 1 since we are now sending an alert.
newAlert.setLastSent(new Date());
newAlert.setName(alertType.getName());
_alertDao.persist(newAlert);
diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java
index a0e74aae012..e88a1025eff 100644
--- a/server/src/com/cloud/api/ApiDBUtils.java
+++ b/server/src/com/cloud/api/ApiDBUtils.java
@@ -33,6 +33,7 @@
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants.DomainDetails;
import org.apache.cloudstack.api.ApiConstants.HostDetails;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
@@ -1852,8 +1853,8 @@ public static ImageStoreResponse fillImageStoreDetails(ImageStoreResponse vrData
return s_imageStoreJoinDao.newImageStoreView(vr);
}
- public static DomainResponse newDomainResponse(ResponseView view, DomainJoinVO ve) {
- return s_domainJoinDao.newDomainResponse(view, ve);
+ public static DomainResponse newDomainResponse(ResponseView view, EnumSet<DomainDetails> details, DomainJoinVO ve) {
+ return s_domainJoinDao.newDomainResponse(view, details, ve);
}
public static AccountResponse newAccountResponse(ResponseView view, AccountJoinVO ve) {
diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java
index 7d7f0fdcdae..82f93978088 100644
--- a/server/src/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/com/cloud/api/ApiResponseHelper.java
@@ -480,6 +480,7 @@ public SnapshotResponse createSnapshotResponse(Snapshot snapshot) {
snapshotResponse.setVolumeId(volume.getUuid());
snapshotResponse.setVolumeName(volume.getName());
snapshotResponse.setVolumeType(volume.getVolumeType().name());
+ snapshotResponse.setVirtualSize(volume.getSize());
DataCenter zone = ApiDBUtils.findZoneById(volume.getDataCenterId());
if (zone != null) {
snapshotResponse.setZoneId(zone.getUuid());
@@ -888,6 +889,7 @@ public LoadBalancerResponse createLoadBalancerResponse(LoadBalancer loadBalancer
DataCenter zone = ApiDBUtils.findZoneById(publicIp.getDataCenterId());
if (zone != null) {
lbResponse.setZoneId(zone.getUuid());
+ lbResponse.setZoneName(zone.getName());
}
//set tag information
@@ -958,6 +960,7 @@ public PodResponse createPodResponse(Pod pod, Boolean showCapacities) {
for (SummedCapacity capacity : capacities) {
CapacityResponse capacityResponse = new CapacityResponse();
capacityResponse.setCapacityType(capacity.getCapacityType());
+ capacityResponse.setCapacityName(CapacityVO.getCapacityName(capacity.getCapacityType()));
capacityResponse.setCapacityUsed(capacity.getUsedCapacity() + capacity.getReservedCapacity());
if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED) {
List<SummedCapacity> c = ApiDBUtils.findNonSharedStorageForClusterPodZone(null, pod.getId(), null);
@@ -994,6 +997,7 @@ public ZoneResponse createZoneResponse(ResponseView view, DataCenter dataCenter,
for (SummedCapacity capacity : capacities) {
CapacityResponse capacityResponse = new CapacityResponse();
capacityResponse.setCapacityType(capacity.getCapacityType());
+ capacityResponse.setCapacityName(CapacityVO.getCapacityName(capacity.getCapacityType()));
capacityResponse.setCapacityUsed(capacity.getUsedCapacity() + capacity.getReservedCapacity());
if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED) {
List<SummedCapacity> c = ApiDBUtils.findNonSharedStorageForClusterPodZone(zoneId, null, null);
@@ -1026,6 +1030,7 @@ public ZoneResponse createZoneResponse(ResponseView view, DataCenter dataCenter,
for (CapacityVO capacity : capacities) {
CapacityResponse capacityResponse = new CapacityResponse();
capacityResponse.setCapacityType(capacity.getCapacityType());
+ capacityResponse.setCapacityName(CapacityVO.getCapacityName(capacity.getCapacityType()));
capacityResponse.setCapacityUsed(capacity.getUsedCapacity());
capacityResponse.setCapacityTotal(capacity.getTotalCapacity());
if (capacityResponse.getCapacityTotal() != 0) {
@@ -1110,6 +1115,7 @@ public ClusterResponse createClusterResponse(Cluster cluster, Boolean showCapaci
for (SummedCapacity capacity : capacities) {
CapacityResponse capacityResponse = new CapacityResponse();
capacityResponse.setCapacityType(capacity.getCapacityType());
+ capacityResponse.setCapacityName(CapacityVO.getCapacityName(capacity.getCapacityType()));
capacityResponse.setCapacityUsed(capacity.getUsedCapacity() + capacity.getReservedCapacity());
if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED) {
@@ -1267,13 +1273,11 @@ public DomainRouterResponse createDomainRouterResponse(VirtualRouter router) {
@Override
public SystemVmResponse createSystemVmResponse(VirtualMachine vm) {
SystemVmResponse vmResponse = new SystemVmResponse();
- if (vm.getType() == Type.SecondaryStorageVm || vm.getType() == Type.ConsoleProxy || vm.getType() == Type.DomainRouter) {
- // SystemVm vm = (SystemVm) systemVM;
+ if (vm.getType() == Type.SecondaryStorageVm || vm.getType() == Type.ConsoleProxy || vm.getType() == Type.DomainRouter || vm.getType() == Type.NetScalerVm) {
vmResponse.setId(vm.getUuid());
- // vmResponse.setObjectId(vm.getId());
vmResponse.setSystemVmType(vm.getType().toString().toLowerCase());
-
vmResponse.setName(vm.getHostName());
+
if (vm.getPodIdToDeployIn() != null) {
HostPodVO pod = ApiDBUtils.findPodById(vm.getPodIdToDeployIn());
if (pod != null) {
@@ -1608,7 +1612,11 @@ public EventResponse createEventResponse(Event event) {
for (Capacity summedCapacity : result) {
CapacityResponse capacityResponse = new CapacityResponse();
capacityResponse.setCapacityTotal(summedCapacity.getTotalCapacity());
+ if (summedCapacity.getAllocatedCapacity() != null) {
+ capacityResponse.setCapacityAllocated(summedCapacity.getAllocatedCapacity());
+ }
capacityResponse.setCapacityType(summedCapacity.getCapacityType());
+ capacityResponse.setCapacityName(CapacityVO.getCapacityName(summedCapacity.getCapacityType()));
capacityResponse.setCapacityUsed(summedCapacity.getUsedCapacity());
if (summedCapacity.getPodId() != null) {
capacityResponse.setPodId(ApiDBUtils.findPodById(summedCapacity.getPodId()).getUuid());
@@ -1679,6 +1687,7 @@ public EventResponse createEventResponse(Event event) {
capacityResponse.setClusterName(cluster.getName());
}
capacityResponse.setCapacityType(Capacity.CAPACITY_TYPE_GPU);
+ capacityResponse.setCapacityName(CapacityVO.getCapacityName(Capacity.CAPACITY_TYPE_GPU));
capacityResponse.setCapacityUsed((long)Math.ceil(capacityUsed));
capacityResponse.setCapacityTotal(capacityMax);
if (capacityMax > 0) {
@@ -3241,9 +3250,21 @@ public UsageRecordResponse createUsageResponse(Usage usageRecord) {
//Hypervisor Type
usageRecResponse.setType(usageRecord.getType());
//Dynamic compute offerings details
- usageRecResponse.setCpuNumber(usageRecord.getCpuCores());
- usageRecResponse.setCpuSpeed(usageRecord.getCpuSpeed());
- usageRecResponse.setMemory(usageRecord.getMemory());
+ if(usageRecord.getCpuCores() != null) {
+ usageRecResponse.setCpuNumber(usageRecord.getCpuCores());
+ } else if (svcOffering.getCpu() != null){
+ usageRecResponse.setCpuNumber(svcOffering.getCpu().longValue());
+ }
+ if(usageRecord.getCpuSpeed() != null) {
+ usageRecResponse.setCpuSpeed(usageRecord.getCpuSpeed());
+ } else if(svcOffering.getSpeed() != null){
+ usageRecResponse.setCpuSpeed(svcOffering.getSpeed().longValue());
+ }
+ if(usageRecord.getMemory() != null) {
+ usageRecResponse.setMemory(usageRecord.getMemory());
+ } else if(svcOffering.getRamSize() != null) {
+ usageRecResponse.setMemory(svcOffering.getRamSize().longValue());
+ }
} else if (usageRecord.getUsageType() == UsageTypes.IP_ADDRESS) {
//isSourceNAT
@@ -3259,7 +3280,7 @@ public UsageRecordResponse createUsageResponse(Usage usageRecord) {
} else if (usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_SENT || usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_RECEIVED) {
//Device Type
usageRecResponse.setType(usageRecord.getType());
- if (usageRecord.getType().equals("DomainRouter")) {
+ if (usageRecord.getType().equals("DomainRouter") || usageRecord.getType().equals("UserVm")) {
//Domain Router Id
VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getUsageId().toString());
if (vm != null) {
diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java
index 40c95a06ea7..9e237741c96 100644
--- a/server/src/com/cloud/api/ApiServer.java
+++ b/server/src/com/cloud/api/ApiServer.java
@@ -487,8 +487,7 @@ public void checkCharacterInkParams(final Map params) {
final Pattern pattern = Pattern.compile(CONTROL_CHARACTERS);
final Matcher matcher = pattern.matcher(value[0]);
if (matcher.find()) {
- throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Received value " + value[0] + " for parameter " + key +
- " is invalid, contains illegal ASCII non-printable characters");
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Received value containing illegal ASCII non-printable characters for parameter " + key);
}
}
stringMap.put(key, value[0]);
diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java
index be165bae813..1c5c70c9852 100644
--- a/server/src/com/cloud/api/query/QueryManagerImpl.java
+++ b/server/src/com/cloud/api/query/QueryManagerImpl.java
@@ -1878,7 +1878,7 @@
respView = ResponseView.Full;
}
- List<DomainResponse> domainResponses = ViewResponseHelper.createDomainResponse(respView, result.first().toArray(
+ List<DomainResponse> domainResponses = ViewResponseHelper.createDomainResponse(respView, cmd.getDetails(), result.first().toArray(
new DomainJoinVO[result.first().size()]));
response.setResponses(domainResponses, result.second());
return response;
@@ -3092,6 +3092,7 @@ private boolean isPermissible(Long accountDomainId, Long offeringDomainId) {
boolean showDomr = ((templateFilter != TemplateFilter.selfexecutable) && (templateFilter != TemplateFilter.featured));
HypervisorType hypervisorType = HypervisorType.getType(cmd.getHypervisor());
+
return searchForTemplatesInternal(id, cmd.getTemplateName(), cmd.getKeyword(), templateFilter, false, null,
cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(), hypervisorType, showDomr,
cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags, showRemovedTmpl,
@@ -3147,13 +3148,13 @@ private boolean isPermissible(Long accountDomainId, Long offeringDomainId) {
ex.addProxyObject(template.getUuid(), "templateId");
throw ex;
}
- if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
+ if (!template.isPublicTemplate() && caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
Account template_acc = _accountMgr.getAccount(template.getAccountId());
DomainVO domain = _domainDao.findById(template_acc.getDomainId());
_accountMgr.checkAccess(caller, domain);
+ }
-
- }// if template is not public, perform permission check here
+ // if template is not public, perform permission check here
else if (!template.isPublicTemplate() && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) {
_accountMgr.checkAccess(caller, null, false, template);
}
@@ -3355,7 +3356,7 @@ else if (!template.isPublicTemplate() && caller.getType() != Account.ACCOUNT_TYP
if (showRemovedTmpl) {
uniqueTmplPair = _templateJoinDao.searchIncludingRemovedAndCount(sc, searchFilter);
} else {
- sc.addAnd("templateState", SearchCriteria.Op.IN, new State[]{State.Active, State.NotUploaded, State.UploadInProgress});
+ sc.addAnd("templateState", SearchCriteria.Op.IN, new State[]{State.Active, State.UploadAbandoned, State.UploadError, State.NotUploaded, State.UploadInProgress});
uniqueTmplPair = _templateJoinDao.searchAndCount(sc, searchFilter);
}
diff --git a/server/src/com/cloud/api/query/ViewResponseHelper.java b/server/src/com/cloud/api/query/ViewResponseHelper.java
index bc418431a13..dfed7ba4f25 100644
--- a/server/src/com/cloud/api/query/ViewResponseHelper.java
+++ b/server/src/com/cloud/api/query/ViewResponseHelper.java
@@ -24,6 +24,7 @@
import org.apache.log4j.Logger;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
+import org.apache.cloudstack.api.ApiConstants.DomainDetails;
import org.apache.cloudstack.api.ApiConstants.HostDetails;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
@@ -348,10 +349,10 @@
return new ArrayList<StoragePoolResponse>(vrDataList.values());
}
- public static List<DomainResponse> createDomainResponse(ResponseView view, DomainJoinVO... domains) {
+ public static List<DomainResponse> createDomainResponse(ResponseView view, EnumSet<DomainDetails> details, DomainJoinVO... domains) {
List<DomainResponse> respList = new ArrayList<DomainResponse>();
for (DomainJoinVO vt : domains){
- respList.add(ApiDBUtils.newDomainResponse(view, vt));
+ respList.add(ApiDBUtils.newDomainResponse(view, details, vt));
}
return respList;
}
diff --git a/server/src/com/cloud/api/query/dao/DataCenterJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/DataCenterJoinDaoImpl.java
index 97a7497a215..ffc75307182 100644
--- a/server/src/com/cloud/api/query/dao/DataCenterJoinDaoImpl.java
+++ b/server/src/com/cloud/api/query/dao/DataCenterJoinDaoImpl.java
@@ -76,10 +76,10 @@ public ZoneResponse newDataCenterResponse(ResponseView view, DataCenterJoinVO da
zoneResponse.setInternalDns2(dataCenter.getInternalDns2());
// FIXME zoneResponse.setVlan(dataCenter.get.getVnet());
zoneResponse.setGuestCidrAddress(dataCenter.getGuestNetworkCidr());
- }
- if (showCapacities != null && showCapacities) {
- zoneResponse.setCapacitites(ApiResponseHelper.getDataCenterCapacityResponse(dataCenter.getId()));
+ if (showCapacities != null && showCapacities) {
+ zoneResponse.setCapacitites(ApiResponseHelper.getDataCenterCapacityResponse(dataCenter.getId()));
+ }
}
// set network domain info
diff --git a/server/src/com/cloud/api/query/dao/DomainJoinDao.java b/server/src/com/cloud/api/query/dao/DomainJoinDao.java
index 164679c531a..94efc28d2d4 100644
--- a/server/src/com/cloud/api/query/dao/DomainJoinDao.java
+++ b/server/src/com/cloud/api/query/dao/DomainJoinDao.java
@@ -16,6 +16,9 @@
// under the License.
package com.cloud.api.query.dao;
+import java.util.EnumSet;
+
+import org.apache.cloudstack.api.ApiConstants.DomainDetails;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.ResourceLimitAndCountResponse;
@@ -26,7 +29,7 @@
public interface DomainJoinDao extends GenericDao<DomainJoinVO, Long> {
- DomainResponse newDomainResponse(ResponseView view, DomainJoinVO vol);
+ DomainResponse newDomainResponse(ResponseView view, EnumSet<DomainDetails> details, DomainJoinVO vol);
DomainJoinVO newDomainView(Domain vol);
diff --git a/server/src/com/cloud/api/query/dao/DomainJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/DomainJoinDaoImpl.java
index 6aecb8159dd..1f123cdab17 100644
--- a/server/src/com/cloud/api/query/dao/DomainJoinDaoImpl.java
+++ b/server/src/com/cloud/api/query/dao/DomainJoinDaoImpl.java
@@ -16,9 +16,11 @@
// under the License.
package com.cloud.api.query.dao;
+import java.util.EnumSet;
import java.util.List;
+import org.apache.cloudstack.api.ApiConstants.DomainDetails;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.ResourceLimitAndCountResponse;
@@ -49,7 +51,7 @@ protected DomainJoinDaoImpl() {
}
@Override
- public DomainResponse newDomainResponse(ResponseView view, DomainJoinVO domain) {
+ public DomainResponse newDomainResponse(ResponseView view, EnumSet<DomainDetails> details, DomainJoinVO domain) {
DomainResponse domainResponse = new DomainResponse();
domainResponse.setDomainName(domain.getName());
domainResponse.setId(domain.getUuid());
@@ -72,17 +74,19 @@ public DomainResponse newDomainResponse(ResponseView view, DomainJoinVO domain)
domainResponse.setState(domain.getState().toString());
domainResponse.setNetworkDomain(domain.getNetworkDomain());
- boolean fullView = (view == ResponseView.Full && domain.getId() == Domain.ROOT_DOMAIN);
- setResourceLimits(domain, fullView, domainResponse);
-
- //get resource limits for projects
- long projectLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getProjectLimit(), fullView, ResourceType.project, domain.getId());
- String projectLimitDisplay = (fullView || projectLimit == -1) ? "Unlimited" : String.valueOf(projectLimit);
- long projectTotal = (domain.getProjectTotal() == null) ? 0 : domain.getProjectTotal();
- String projectAvail = (fullView || projectLimit == -1) ? "Unlimited" : String.valueOf(projectLimit - projectTotal);
- domainResponse.setProjectLimit(projectLimitDisplay);
- domainResponse.setProjectTotal(projectTotal);
- domainResponse.setProjectAvailable(projectAvail);
+ if (details.contains(DomainDetails.all) || details.contains(DomainDetails.resource)) {
+ boolean fullView = (view == ResponseView.Full && domain.getId() == Domain.ROOT_DOMAIN);
+ setResourceLimits(domain, fullView, domainResponse);
+
+ //get resource limits for projects
+ long projectLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getProjectLimit(), fullView, ResourceType.project, domain.getId());
+ String projectLimitDisplay = (fullView || projectLimit == -1) ? "Unlimited" : String.valueOf(projectLimit);
+ long projectTotal = (domain.getProjectTotal() == null) ? 0 : domain.getProjectTotal();
+ String projectAvail = (fullView || projectLimit == -1) ? "Unlimited" : String.valueOf(projectLimit - projectTotal);
+ domainResponse.setProjectLimit(projectLimitDisplay);
+ domainResponse.setProjectTotal(projectTotal);
+ domainResponse.setProjectAvailable(projectAvail);
+ }
domainResponse.setObjectName("domain");
diff --git a/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java
index 3d8cc948944..4d411f2f2b4 100644
--- a/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java
+++ b/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java
@@ -50,6 +50,9 @@
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
+import org.apache.cloudstack.ha.HAResource;
+import org.apache.cloudstack.ha.dao.HAConfigDao;
+
@Component
public class HostJoinDaoImpl extends GenericDaoBase<HostJoinVO, Long> implements HostJoinDao {
public static final Logger s_logger = Logger.getLogger(HostJoinDaoImpl.class);
@@ -59,6 +62,8 @@
@Inject
private HostDetailsDao hostDetailsDao;
@Inject
+ private HAConfigDao haConfigDao;
+ @Inject
private OutOfBandManagementDao outOfBandManagementDao;
private final SearchBuilder<HostJoinVO> hostSearch;
@@ -231,6 +236,7 @@ public HostResponse newHostResponse(HostJoinVO host, EnumSet<HostDetails> detail
}
}
+ hostResponse.setHostHAResponse(haConfigDao.findHAResource(host.getId(), HAResource.ResourceType.Host));
hostResponse.setOutOfBandManagementResponse(outOfBandManagementDao.findByHost(host.getId()));
hostResponse.setResourceState(host.getResourceState().toString());
@@ -239,6 +245,9 @@ public HostResponse newHostResponse(HostJoinVO host, EnumSet<HostDetails> detail
hostResponse.setJobId(host.getJobUuid());
hostResponse.setJobStatus(host.getJobStatus());
}
+ hostResponse.setAnnotation(host.getAnnotation());
+ hostResponse.setLastAnnotated(host.getLastAnnotated ());
+ hostResponse.setUsername(host.getUsername());
hostResponse.setObjectName("host");
diff --git a/server/src/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java
index f51f52e2f8d..37fdaefefcf 100644
--- a/server/src/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java
+++ b/server/src/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java
@@ -16,16 +16,6 @@
// under the License.
package com.cloud.api.query.dao;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.inject.Inject;
-
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
-import org.apache.cloudstack.api.response.StoragePoolResponse;
-import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
-
import com.cloud.api.ApiDBUtils;
import com.cloud.api.query.vo.StoragePoolJoinVO;
import com.cloud.capacity.CapacityManager;
@@ -35,6 +25,14 @@
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
+import org.apache.cloudstack.api.response.StoragePoolResponse;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import javax.inject.Inject;
+import java.util.ArrayList;
+import java.util.List;
@Component
public class StoragePoolJoinDaoImpl extends GenericDaoBase<StoragePoolJoinVO, Long> implements StoragePoolJoinDao {
@@ -98,6 +96,7 @@ public StoragePoolResponse newStoragePoolResponse(StoragePoolJoinVO pool) {
poolResponse.setClusterId(pool.getClusterUuid());
poolResponse.setClusterName(pool.getClusterName());
+ poolResponse.setProvider(pool.getStorageProviderName());
poolResponse.setTags(pool.getTag());
poolResponse.setOverProvisionFactor(Double.toString(CapacityManager.StorageOverprovisioningFactor.valueIn(pool.getId())));
@@ -163,6 +162,7 @@ public StoragePoolResponse newStoragePoolForMigrationResponse(StoragePoolJoinVO
poolResponse.setClusterId(pool.getClusterUuid());
poolResponse.setClusterName(pool.getClusterName());
+ poolResponse.setProvider(pool.getStorageProviderName());
poolResponse.setTags(pool.getTag());
// set async job
diff --git a/server/src/com/cloud/api/query/dao/TemplateJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/TemplateJoinDaoImpl.java
index 92a2e20bd7f..67105d0d88e 100644
--- a/server/src/com/cloud/api/query/dao/TemplateJoinDaoImpl.java
+++ b/server/src/com/cloud/api/query/dao/TemplateJoinDaoImpl.java
@@ -105,7 +105,9 @@ private String getTemplateStatus(TemplateJoinVO template) {
} else {
templateStatus = template.getDownloadPercent() + "% Downloaded";
}
- } else {
+ }else if (template.getErrorString()==null){
+ templateStatus = template.getTemplateState().toString();
+ }else {
templateStatus = template.getErrorString();
}
} else if (template.getDownloadState() == VMTemplateHostVO.Status.DOWNLOADED) {
@@ -171,6 +173,11 @@ public TemplateResponse newTemplateResponse(ResponseView view, TemplateJoinVO te
templateResponse.setSize(templateSize);
}
+ Long templatePhysicalSize = template.getPhysicalSize();
+ if (templatePhysicalSize > 0) {
+ templateResponse.setPhysicalSize(templatePhysicalSize);
+ }
+
templateResponse.setChecksum(template.getChecksum());
if (template.getSourceTemplateId() != null) {
templateResponse.setSourceTemplateId(template.getSourceTemplateUuid());
@@ -405,7 +412,7 @@ public TemplateResponse newIsoResponse(TemplateJoinVO iso) {
}
SearchCriteria<TemplateJoinVO> sc = tmpltIdPairSearch.create();
if (!showRemoved) {
- sc.setParameters("templateState", VirtualMachineTemplate.State.Active, VirtualMachineTemplate.State.NotUploaded, VirtualMachineTemplate.State.UploadInProgress);
+ sc.setParameters("templateState", VirtualMachineTemplate.State.Active, VirtualMachineTemplate.State.UploadAbandoned, VirtualMachineTemplate.State.UploadError ,VirtualMachineTemplate.State.NotUploaded, VirtualMachineTemplate.State.UploadInProgress);
}
sc.setParameters("tempZonePairIN", labels);
List<TemplateJoinVO> vms = searchIncludingRemoved(sc, searchFilter, null, false);
diff --git a/server/src/com/cloud/api/query/dao/UserAccountJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/UserAccountJoinDaoImpl.java
index 433912bff28..8d06bcd0a26 100644
--- a/server/src/com/cloud/api/query/dao/UserAccountJoinDaoImpl.java
+++ b/server/src/com/cloud/api/query/dao/UserAccountJoinDaoImpl.java
@@ -58,6 +58,7 @@ public UserResponse newUserResponse(UserAccountJoinVO usr) {
userResponse.setAccountId(usr.getAccountUuid());
userResponse.setAccountName(usr.getAccountName());
userResponse.setAccountType(usr.getAccountType());
+ userResponse.setUserSource(usr.getSource());
userResponse.setCreated(usr.getCreated());
userResponse.setDomainId(usr.getDomainUuid());
userResponse.setDomainName(usr.getDomainName());
diff --git a/server/src/com/cloud/api/query/vo/HostJoinVO.java b/server/src/com/cloud/api/query/vo/HostJoinVO.java
index dcd058fce10..2afe1910964 100644
--- a/server/src/com/cloud/api/query/vo/HostJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/HostJoinVO.java
@@ -27,15 +27,16 @@
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
-import org.apache.cloudstack.api.Identity;
-import org.apache.cloudstack.api.InternalIdentity;
-
import com.cloud.host.Host.Type;
import com.cloud.host.Status;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.org.Cluster;
import com.cloud.resource.ResourceState;
+import com.cloud.utils.StringUtils;
import com.cloud.utils.db.GenericDao;
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.api.InternalIdentity;
+import org.apache.cloudstack.ha.HAConfig;
import org.apache.cloudstack.outofbandmanagement.OutOfBandManagement;
/**
@@ -99,6 +100,15 @@
@Enumerated(value = EnumType.STRING)
private OutOfBandManagement.PowerState outOfBandManagementPowerState;
+ @Column(name = "ha_enabled")
+ private boolean hostHAEnabled = false;
+
+ @Column(name = "ha_state")
+ private HAConfig.HAState hostHAState;
+
+ @Column(name = "ha_provider")
+ private String hostHAProvider;
+
@Column(name = "resource_state")
@Enumerated(value = EnumType.STRING)
private ResourceState resourceState;
@@ -182,6 +192,15 @@
@Column(name = "job_status")
private int jobStatus;
+ @Column(name = "annotation")
+ private String annotation;
+
+ @Column(name = "last_annotated")
+ private Date lastAnnotated;
+
+ @Column(name = "username")
+ private String username;
+
@Override
public long getId() {
return this.id;
@@ -260,6 +279,18 @@ public boolean isOutOfBandManagementEnabled() {
return outOfBandManagementPowerState;
}
+ public boolean isHostHAEnabled() {
+ return hostHAEnabled;
+ }
+
+ public HAConfig.HAState getHostHAState() {
+ return hostHAState;
+ }
+
+ public String getHostHAProvider() {
+ return hostHAProvider;
+ }
+
public ResourceState getResourceState() {
return resourceState;
}
@@ -355,4 +386,20 @@ public long getCpuReservedCapacity() {
public String getTag() {
return tag;
}
+
+ public String getAnnotation() {
+ return annotation;
+ }
+
+ public Date getLastAnnotated() {
+ return lastAnnotated;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public boolean isAnnotated() {
+ return StringUtils.isNotBlank(annotation);
+ }
}
diff --git a/server/src/com/cloud/api/query/vo/TemplateJoinVO.java b/server/src/com/cloud/api/query/vo/TemplateJoinVO.java
index 43a9c3b09cc..15a748bce41 100644
--- a/server/src/com/cloud/api/query/vo/TemplateJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/TemplateJoinVO.java
@@ -196,6 +196,9 @@
@Column(name = "size")
private long size;
+ @Column(name = "physical_size")
+ private long physicalSize;
+
@Column(name = "template_state")
@Enumerated(EnumType.STRING)
private State templateState;
@@ -409,6 +412,10 @@ public long getSize() {
return size;
}
+ public long getPhysicalSize() {
+ return physicalSize;
+ }
+
public boolean isDestroyed() {
return destroyed;
}
diff --git a/server/src/com/cloud/api/query/vo/UserAccountJoinVO.java b/server/src/com/cloud/api/query/vo/UserAccountJoinVO.java
index e6b1ace0966..88f5efa343f 100644
--- a/server/src/com/cloud/api/query/vo/UserAccountJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/UserAccountJoinVO.java
@@ -16,19 +16,20 @@
// under the License.
package com.cloud.api.query.vo;
-import java.util.Date;
+import com.cloud.user.User;
+import com.cloud.user.UserAccount;
+import com.cloud.utils.db.Encrypt;
+import com.cloud.utils.db.GenericDao;
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.api.InternalIdentity;
import javax.persistence.Column;
import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
import javax.persistence.Id;
import javax.persistence.Table;
-
-import org.apache.cloudstack.api.Identity;
-import org.apache.cloudstack.api.InternalIdentity;
-
-import com.cloud.user.UserAccount;
-import com.cloud.utils.db.Encrypt;
-import com.cloud.utils.db.GenericDao;
+import java.util.Date;
@Entity
@Table(name = "user_view")
@@ -123,6 +124,10 @@
@Column(name = "default")
boolean isDefault;
+ @Column(name = "source")
+ @Enumerated(value = EnumType.STRING)
+ private User.Source source;
+
public UserAccountJoinVO() {
}
@@ -258,4 +263,8 @@ public String getProjectUuid() {
public String getProjectName() {
return null;
}
+
+ public User.Source getSource() {
+ return source;
+ }
}
diff --git a/server/src/com/cloud/capacity/CapacityManagerImpl.java b/server/src/com/cloud/capacity/CapacityManagerImpl.java
index caf91a9db82..9cc5e4271b6 100644
--- a/server/src/com/cloud/capacity/CapacityManagerImpl.java
+++ b/server/src/com/cloud/capacity/CapacityManagerImpl.java
@@ -591,6 +591,8 @@ public void updateCapacityForHost(final Host host) {
offeringsMap.put(offering.getId(), offering);
}
+ long usedCpuCore = 0;
+ long reservedCpuCore = 0;
long usedCpu = 0;
long usedMemory = 0;
long reservedMemory = 0;
@@ -626,9 +628,11 @@ public void updateCapacityForHost(final Host host) {
usedCpu +=
((Integer.parseInt(vmDetails.get(UsageEventVO.DynamicParameters.cpuNumber.name())) * Integer.parseInt(vmDetails.get(UsageEventVO.DynamicParameters.cpuSpeed.name()))) / cpuOvercommitRatio) *
clusterCpuOvercommitRatio;
+ usedCpuCore += Integer.parseInt(vmDetails.get(UsageEventVO.DynamicParameters.cpuNumber.name()));
} else {
usedMemory += ((so.getRamSize() * 1024L * 1024L) / ramOvercommitRatio) * clusterRamOvercommitRatio;
usedCpu += ((so.getCpu() * so.getSpeed()) / cpuOvercommitRatio) * clusterCpuOvercommitRatio;
+ usedCpuCore += so.getCpu();
}
}
@@ -655,9 +659,11 @@ public void updateCapacityForHost(final Host host) {
reservedCpu +=
((Integer.parseInt(vmDetails.get(UsageEventVO.DynamicParameters.cpuNumber.name())) * Integer.parseInt(vmDetails.get(UsageEventVO.DynamicParameters.cpuSpeed.name()))) / cpuOvercommitRatio) *
clusterCpuOvercommitRatio;
+ reservedCpuCore += Integer.parseInt(vmDetails.get(UsageEventVO.DynamicParameters.cpuNumber.name()));
} else {
reservedMemory += ((so.getRamSize() * 1024L * 1024L) / ramOvercommitRatio) * clusterRamOvercommitRatio;
reservedCpu += (so.getCpu() * so.getSpeed() / cpuOvercommitRatio) * clusterCpuOvercommitRatio;
+ reservedCpuCore += so.getCpu();
}
} else {
// signal if not done already, that the VM has been stopped for skip.counting.hours,
@@ -678,6 +684,53 @@ public void updateCapacityForHost(final Host host) {
CapacityVO cpuCap = _capacityDao.findByHostIdType(host.getId(), Capacity.CAPACITY_TYPE_CPU);
CapacityVO memCap = _capacityDao.findByHostIdType(host.getId(), Capacity.CAPACITY_TYPE_MEMORY);
+ CapacityVO cpuCoreCap = _capacityDao.findByHostIdType(host.getId(), CapacityVO.CAPACITY_TYPE_CPU_CORE);
+
+ if (cpuCoreCap != null) {
+ long hostTotalCpuCore = host.getCpus().longValue();
+
+ if (cpuCoreCap.getTotalCapacity() != hostTotalCpuCore) {
+ s_logger.debug("Calibrate total cpu for host: " + host.getId() + " old total CPU:"
+ + cpuCoreCap.getTotalCapacity() + " new total CPU:" + hostTotalCpuCore);
+ cpuCoreCap.setTotalCapacity(hostTotalCpuCore);
+
+ }
+
+ if (cpuCoreCap.getUsedCapacity() == usedCpuCore && cpuCoreCap.getReservedCapacity() == reservedCpuCore) {
+ s_logger.debug("No need to calibrate cpu capacity, host:" + host.getId() + " usedCpuCore: " + cpuCoreCap.getUsedCapacity()
+ + " reservedCpuCore: " + cpuCoreCap.getReservedCapacity());
+ } else {
+ if (cpuCoreCap.getReservedCapacity() != reservedCpuCore) {
+ s_logger.debug("Calibrate reserved cpu core for host: " + host.getId() + " old reservedCpuCore:"
+ + cpuCoreCap.getReservedCapacity() + " new reservedCpuCore:" + reservedCpuCore);
+ cpuCoreCap.setReservedCapacity(reservedCpuCore);
+ }
+ if (cpuCoreCap.getUsedCapacity() != usedCpuCore) {
+ s_logger.debug("Calibrate used cpu core for host: " + host.getId() + " old usedCpuCore:"
+ + cpuCoreCap.getUsedCapacity() + " new usedCpuCore:" + usedCpuCore);
+ cpuCoreCap.setUsedCapacity(usedCpuCore);
+ }
+ }
+ try {
+ _capacityDao.update(cpuCoreCap.getId(), cpuCoreCap);
+ } catch (Exception e) {
+ s_logger.error("Caught exception while updating cpucore capacity for the host " +host.getId(), e);
+ }
+ } else {
+ final long usedCpuCoreFinal = usedCpuCore;
+ final long reservedCpuCoreFinal = reservedCpuCore;
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ CapacityVO capacity = new CapacityVO(host.getId(), host.getDataCenterId(), host.getPodId(), host.getClusterId(), usedCpuCoreFinal, host.getCpus().longValue(),
+ CapacityVO.CAPACITY_TYPE_CPU_CORE);
+ capacity.setReservedCapacity(reservedCpuCoreFinal);
+ capacity.setCapacityState(capacityState);
+ _capacityDao.persist(capacity);
+ }
+ });
+ }
+
if (cpuCap != null && memCap != null) {
if (host.getTotalMemory() != null) {
memCap.setTotalCapacity(host.getTotalMemory());
diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java
index 09c502d6b63..6f48eab68a3 100644
--- a/server/src/com/cloud/configuration/Config.java
+++ b/server/src/com/cloud/configuration/Config.java
@@ -16,6 +16,15 @@
// under the License.
package com.cloud.configuration;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
+import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
+import org.apache.cloudstack.framework.config.ConfigKey;
+
import com.cloud.agent.AgentManager;
import com.cloud.consoleproxy.ConsoleProxyManager;
import com.cloud.ha.HighAvailabilityManager;
@@ -29,14 +38,6 @@
import com.cloud.template.TemplateManager;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.snapshot.VMSnapshotManager;
-import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
-import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
-import org.apache.cloudstack.framework.config.ConfigKey;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.StringTokenizer;
public enum Config {
@@ -182,14 +183,6 @@
"3600",
"Timeout (in seconds) to synchronize storage pool operations.",
null),
- StorageTemplateCleanupEnabled(
- "Storage",
- ManagementServer.class,
- Boolean.class,
- "storage.template.cleanup.enabled",
- "true",
- "Enable/disable template cleanup activity, only take effect when overall storage cleanup is enabled",
- null),
PrimaryStorageDownloadWait(
"Storage",
TemplateManager.class,
@@ -499,14 +492,6 @@
"The time interval in seconds when the management server polls for snapshots to be scheduled.",
null),
SnapshotDeltaMax("Snapshots", SnapshotManager.class, Integer.class, "snapshot.delta.max", "16", "max delta snapshots between two full snapshots.", null),
- BackupSnapshotAfterTakingSnapshot(
- "Snapshots",
- SnapshotManager.class,
- Boolean.class,
- "snapshot.backup.rightafter",
- "true",
- "backup snapshot right after snapshot is taken",
- null),
KVMSnapshotEnabled("Hidden", SnapshotManager.class, Boolean.class, "kvm.snapshot.enabled", "false", "whether snapshot is enabled for KVM hosts", null),
// Advanced
@@ -811,7 +796,14 @@
"600",
"Time Interval to fetch the LB health check states (in sec)",
null),
-
+ NCCCmdTimeOut(
+ "Advanced",
+ ManagementServer.class,
+ Long.class,
+ "ncc.command.timeout",
+ "600000", // 10 minutes
+ "Command Timeout Interval (in millisec)",
+ null),
DirectAttachNetworkEnabled(
"Advanced",
ManagementServer.class,
@@ -861,7 +853,6 @@
"60000",
"The interval (in milliseconds) when vm stats are retrieved from agents.",
null),
- VmDiskStatsInterval("Advanced", ManagementServer.class, Integer.class, "vm.disk.stats.interval", "0", "Interval (in seconds) to report vm disk statistics.", null),
VmTransitionWaitInterval(
"Advanced",
ManagementServer.class,
@@ -1211,24 +1202,6 @@
VmwareHungWorkerTimeout("Advanced", ManagementServer.class, Long.class, "vmware.hung.wokervm.timeout", "7200", "Worker VM timeout in seconds", null),
VmwareVcenterSessionTimeout("Advanced", ManagementServer.class, Long.class, "vmware.vcenter.session.timeout", "1200", "VMware client timeout in seconds", null),
- // Midonet
- MidoNetAPIServerAddress(
- "Network",
- ManagementServer.class,
- String.class,
- "midonet.apiserver.address",
- "http://localhost:8081",
- "Specify the address at which the Midonet API server can be contacted (if using Midonet)",
- null),
- MidoNetProviderRouterId(
- "Network",
- ManagementServer.class,
- String.class,
- "midonet.providerrouter.id",
- "d7c5e6a3-e2f4-426b-b728-b7ce6a0448e5",
- "Specifies the UUID of the Midonet provider router (if using Midonet)",
- null),
-
// KVM
KvmPublicNetwork("Hidden", ManagementServer.class, String.class, "kvm.public.network.device", null, "Specify the public bridge on host for public network", null),
KvmPrivateNetwork("Hidden", ManagementServer.class, String.class, "kvm.private.network.device", null, "Specify the private bridge on host for private network", null),
@@ -1452,15 +1425,6 @@
"The default maximum secondary storage space (in GiB) that can be used for an account",
null),
- ResourceCountCheckInterval(
- "Advanced",
- ManagementServer.class,
- Long.class,
- "resourcecount.check.interval",
- "0",
- "Time (in seconds) to wait before retrying resource count check task. Default is 0 which is to never run the task",
- "Seconds"),
-
//disabling lb as cluster sync does not work with distributed cluster
SubDomainNetworkAccess(
"Advanced",
diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
index a936e978e3d..bf1c20e118c 100755
--- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -199,6 +199,7 @@
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.StringUtils;
+import com.cloud.utils.UriUtils;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.EntityManager;
@@ -239,8 +240,6 @@
VolumeDao _volumeDao;
@Inject
VMInstanceDao _vmInstanceDao;
- //@Inject
- //VmwareDatacenterZoneMapDao _vmwareDatacenterZoneMapDao;
@Inject
AccountVlanMapDao _accountVlanMapDao;
@Inject
@@ -281,7 +280,6 @@
ClusterDao _clusterDao;
@Inject
AlertManager _alertMgr;
- // @com.cloud.utils.component.Inject(adapter = SecurityChecker.class)
List<SecurityChecker> _secChecker;
@Inject
@@ -815,16 +813,15 @@ private String validateConfigurationValue(final String name, String value, final
if (val <= 0) {
throw new InvalidParameterValueException("Please enter a positive value for the configuration parameter:" + name);
}
- //TODO - better validation for all password pamameters
- if ("vm.password.length".equalsIgnoreCase(name) && val < 10) {
- throw new InvalidParameterValueException("Please enter a value greater than 6 for the configuration parameter:" + name);
+ if ("vm.password.length".equalsIgnoreCase(name) && val < 6) {
+ throw new InvalidParameterValueException("Please enter a value greater than 5 for the configuration parameter:" + name);
}
if ("remote.access.vpn.psk.length".equalsIgnoreCase(name)) {
if (val < 8) {
- throw new InvalidParameterValueException("Please enter a value greater than 8 for the configuration parameter:" + name);
+ throw new InvalidParameterValueException("Please enter a value greater than 7 for the configuration parameter:" + name);
}
if (val > 256) {
- throw new InvalidParameterValueException("Please enter a value less than 256 for the configuration parameter:" + name);
+ throw new InvalidParameterValueException("Please enter a value less than 257 for the configuration parameter:" + name);
}
}
} catch (final NumberFormatException e) {
@@ -1018,12 +1015,6 @@ private void checkPodAttributes(final long podId, final String podName, final lo
final String checkPodCIDRs = _configDao.getValue("check.pod.cidrs");
if (checkPodCIDRs == null || checkPodCIDRs.trim().isEmpty() || Boolean.parseBoolean(checkPodCIDRs)) {
checkPodCidrSubnets(zoneId, podId, cidr);
- /*
- * Commenting out due to Bug 11593 - CIDR conflicts with zone when
- * extending pod but not when creating it
- *
- * checkCidrVlanOverlap(zoneId, cidr);
- */
}
if (allocationStateStr != null && !allocationStateStr.isEmpty()) {
@@ -1586,12 +1577,6 @@ public DataCenter editZone(final UpdateZoneCmd cmd) {
throw new InvalidParameterValueException(
"Invalid Zone Detail specified, fields 'key' and 'value' cannot be null, please specify details in the form: details[0].key=XXX&details[0].value=YYY");
}
- // validate the zone detail keys are known keys
- /*
- * if(!ZoneConfig.doesKeyExist(key)){ throw new
- * InvalidParameterValueException
- * ("Invalid Zone Detail parameter: "+ key); }
- */
newDetails.put(key, value);
}
}
@@ -2052,7 +2037,7 @@ public ServiceOffering createServiceOffering(final CreateServiceOfferingCmd cmd)
if(!allowNetworkRate) {
throw new InvalidParameterValueException("Network rate can be specified only for non-System offering and system offerings having \"domainrouter\" systemvmtype");
}
- if(cmd.getNetworkRate().intValue() < 1) {
+ if(cmd.getNetworkRate().intValue() < 0) {
throw new InvalidParameterValueException("Failed to create service offering " + name + ": specify the network rate value more than 0");
}
}
@@ -2893,7 +2878,7 @@ public Vlan doInTransaction(final TransactionStatus status) {
newVlanNetmask = sameSubnet.second().second();
}
final Vlan vlan = createVlanAndPublicIpRange(zoneId, networkId, physicalNetworkId, forVirtualNetwork, podId, startIP, endIP, newVlanGateway, newVlanNetmask, vlanId,
- domain, vlanOwner, startIPv6, endIPv6, ip6Gateway, ip6Cidr);
+ false, domain, vlanOwner, startIPv6, endIPv6, ip6Gateway, ip6Cidr);
// create an entry in the nic_secondary table. This will be the new
// gateway that will be configured on the corresponding routervm.
return vlan;
@@ -3010,7 +2995,7 @@ public boolean hasSameSubnet(boolean ipv4, String vlanGateway, String vlanNetmas
@Override
@DB
public Vlan createVlanAndPublicIpRange(final long zoneId, final long networkId, final long physicalNetworkId, final boolean forVirtualNetwork, final Long podId, final String startIP, final String endIP,
- final String vlanGateway, final String vlanNetmask, String vlanId, Domain domain, final Account vlanOwner, final String startIPv6, final String endIPv6, final String vlanIp6Gateway, final String vlanIp6Cidr) {
+ final String vlanGateway, final String vlanNetmask, String vlanId, boolean bypassVlanOverlapCheck, Domain domain, final Account vlanOwner, final String startIPv6, final String endIPv6, final String vlanIp6Gateway, final String vlanIp6Cidr) {
final Network network = _networkModel.getNetwork(networkId);
boolean ipv4 = false, ipv6 = false;
@@ -3077,8 +3062,10 @@ public Vlan createVlanAndPublicIpRange(final long zoneId, final long networkId,
final String[] vlan = uri.toString().split("vlan:\\/\\/");
networkVlanId = vlan[1];
// For pvlan
- networkVlanId = networkVlanId.split("-")[0];
- }
+ if (network.getBroadcastDomainType() != BroadcastDomainType.Vlan) {
+ networkVlanId = networkVlanId.split("-")[0];
+ }
+ }
}
if (vlanId != null && !connectivityWithoutVlan) {
@@ -3168,7 +3155,9 @@ public Vlan createVlanAndPublicIpRange(final long zoneId, final long networkId,
continue;
}
// from here, subnet overlaps
- if ( !vlanId.equals(vlan.getVlanTag()) ) {
+ if (!UriUtils.checkVlanUriOverlap(
+ BroadcastDomainType.getValue(BroadcastDomainType.fromString(vlanId)),
+ BroadcastDomainType.getValue(BroadcastDomainType.fromString(vlan.getVlanTag())))) {
boolean overlapped = false;
if( network.getTrafficType() == TrafficType.Public ) {
overlapped = true;
@@ -3239,7 +3228,7 @@ public Vlan createVlanAndPublicIpRange(final long zoneId, final long networkId,
}
// Check if the vlan is being used
- if (_zoneDao.findVnet(zoneId, physicalNetworkId, vlanId).size() > 0) {
+ if (!bypassVlanOverlapCheck && _zoneDao.findVnet(zoneId, physicalNetworkId, BroadcastDomainType.getValue(BroadcastDomainType.fromString(vlanId))).size() > 0) {
throw new InvalidParameterValueException("The VLAN tag " + vlanId + " is already being used for dynamic vlan allocation for the guest network in zone "
+ zone.getName());
}
@@ -3915,7 +3904,7 @@ public NetworkOffering createNetworkOffering(final CreateNetworkOfferingCmd cmd)
final Boolean egressDefaultPolicy = cmd.getEgressDefaultPolicy();
Integer maxconn = null;
boolean enableKeepAlive = false;
-
+ String servicePackageuuid = cmd.getServicePackageId();
// Verify traffic type
for (final TrafficType tType : TrafficType.values()) {
if (tType.name().equalsIgnoreCase(trafficTypeString)) {
@@ -4291,6 +4280,16 @@ public NetworkOfferingVO createNetworkOffering(final String name, final String d
final boolean conserveMode, final Map<Service, Map<Capability, String>> serviceCapabilityMap, final boolean specifyIpRanges, final boolean isPersistent,
final Map<NetworkOffering.Detail, String> details, final boolean egressDefaultPolicy, final Integer maxconn, final boolean enableKeepAlive) {
+ String servicePackageUuid;
+ String spDescription = null;
+ if (details == null) {
+ servicePackageUuid = null;
+ } else {
+ servicePackageUuid = details.get(NetworkOffering.Detail.servicepackageuuid);
+ spDescription = details.get(NetworkOffering.Detail.servicepackagedescription);
+ }
+
+
final String multicastRateStr = _configDao.getValue("multicast.throttling.rate");
final int multicastRate = multicastRateStr == null ? 10 : Integer.parseInt(multicastRateStr);
tags = StringUtils.cleanupTags(tags);
@@ -4449,11 +4448,37 @@ public NetworkOfferingVO createNetworkOffering(final String name, final String d
offeringFinal.setServiceOfferingId(serviceOfferingId);
}
+ //Set Service package id
+ offeringFinal.setServicePackage(servicePackageUuid);
// validate the details
if (details != null) {
validateNtwkOffDetails(details, serviceProviderMap);
}
+ boolean vpcOff = false;
+ boolean nsOff = false;
+
+ if (serviceProviderMap != null && spDescription != null) {
+ for (final Network.Service service : serviceProviderMap.keySet()) {
+ final Set<Provider> providers = serviceProviderMap.get(service);
+ if (providers != null && !providers.isEmpty()) {
+ for (final Network.Provider provider : providers) {
+ if (provider == Provider.VPCVirtualRouter) {
+ vpcOff = true;
+ }
+ if (provider == Provider.Netscaler) {
+ nsOff = true;
+ }
+ }
+ }
+ }
+ if(vpcOff && nsOff) {
+ if(!(spDescription.equalsIgnoreCase("A NetScalerVPX is dedicated per network.") || spDescription.contains("dedicated NetScaler"))) {
+ throw new InvalidParameterValueException("Only NetScaler Service Pacakge with Dedicated Device Mode is Supported in VPC Type Guest Network");
+ }
+ }
+ }
+
return Transaction.execute(new TransactionCallback<NetworkOfferingVO>() {
@Override
public NetworkOfferingVO doInTransaction(final TransactionStatus status) {
@@ -4752,7 +4777,7 @@ protected void validateNtwkOffDetails(final Map<Detail, String> details, final M
// Now apply pagination
final List<? extends NetworkOffering> wPagination = StringUtils.applyPagination(supportedOfferings, cmd.getStartIndex(), cmd.getPageSizeVal());
if (wPagination != null) {
- final Pair<List<? extends NetworkOffering>, Integer> listWPagination = new Pair<List<? extends NetworkOffering>, Integer>(wPagination, offerings.size());
+ final Pair<List<? extends NetworkOffering>, Integer> listWPagination = new Pair<List<? extends NetworkOffering>, Integer>(wPagination, supportedOfferings.size());
return listWPagination;
}
return new Pair<List<? extends NetworkOffering>, Integer>(supportedOfferings, supportedOfferings.size());
@@ -4776,6 +4801,7 @@ public boolean isOfferingForVpc(final NetworkOffering offering) {
return vpcProvider || nuageVpcProvider;
}
+ @DB
@Override
@ActionEvent(eventType = EventTypes.EVENT_NETWORK_OFFERING_DELETE, eventDescription = "deleting network offering")
public boolean deleteNetworkOffering(final DeleteNetworkOfferingCmd cmd) {
diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java
index 1817ade2874..cee07455d3a 100644
--- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java
+++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java
@@ -110,6 +110,7 @@
import com.cloud.utils.DateUtil;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
+import com.cloud.utils.StringUtils;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.GlobalLock;
@@ -1354,7 +1355,7 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl
StringBuilder buf = profile.getBootArgsBuilder();
buf.append(" template=domP type=consoleproxy");
- buf.append(" host=").append(ApiServiceConfiguration.ManagementHostIPAdr.value());
+ buf.append(" host=").append(StringUtils.shuffleCSVList(ApiServiceConfiguration.ManagementHostIPAdr.value()));
buf.append(" port=").append(_mgmtPort);
buf.append(" name=").append(profile.getVirtualMachine().getHostName());
if (_sslEnabled) {
diff --git a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
index c413eddc1a8..0bf1c705759 100644
--- a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
+++ b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
@@ -22,6 +22,7 @@
import javax.inject.Inject;
+import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Command;
@@ -29,9 +30,12 @@
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.gpu.GPU;
+import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkVO;
+import com.cloud.offering.NetworkOffering;
import com.cloud.offering.ServiceOffering;
+import com.cloud.offerings.dao.NetworkOfferingDetailsDao;
import com.cloud.resource.ResourceManager;
import com.cloud.service.ServiceOfferingDetailsVO;
import com.cloud.service.dao.ServiceOfferingDao;
@@ -57,6 +61,8 @@
@Inject
private NetworkDao _networkDao;
@Inject
+ private NetworkOfferingDetailsDao networkOfferingDetailsDao;
+ @Inject
private VMInstanceDao _virtualMachineDao;
@Inject
private UserVmDetailsDao _userVmDetailsDao;
@@ -134,7 +140,21 @@ protected VirtualMachineTO toVirtualMachineTO(VirtualMachineProfile vmProfile) {
NicTO[] nics = new NicTO[nicProfiles.size()];
int i = 0;
for (NicProfile nicProfile : nicProfiles) {
- nics[i++] = toNicTO(nicProfile);
+ if(vm.getType() == VirtualMachine.Type.NetScalerVm) {
+ nicProfile.setBroadcastType(BroadcastDomainType.Native);
+ }
+ NicTO nicTo = toNicTO(nicProfile);
+ final NetworkVO network = _networkDao.findByUuid(nicTo.getNetworkUuid());
+ if (network != null) {
+ final Map<NetworkOffering.Detail, String> details = networkOfferingDetailsDao.getNtwkOffDetails(network.getNetworkOfferingId());
+ if (details != null) {
+ details.putIfAbsent(NetworkOffering.Detail.PromiscuousMode, NetworkOrchestrationService.PromiscuousMode.value().toString());
+ details.putIfAbsent(NetworkOffering.Detail.MacAddressChanges, NetworkOrchestrationService.MacAddressChanges.value().toString());
+ details.putIfAbsent(NetworkOffering.Detail.ForgedTransmits, NetworkOrchestrationService.ForgedTransmits.value().toString());
+ }
+ nicTo.setDetails(details);
+ }
+ nics[i++] = nicTo;
}
to.setNics(nics);
diff --git a/server/src/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java b/server/src/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java
index 13a1a64cd21..ac5b48aa2b5 100644
--- a/server/src/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java
+++ b/server/src/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java
@@ -16,6 +16,23 @@
// under the License.
package com.cloud.hypervisor.kvm.discoverer;
+import java.net.InetAddress;
+import java.net.URI;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.ca.CAManager;
+import org.apache.cloudstack.ca.SetupCertificateCommand;
+import org.apache.cloudstack.framework.ca.Certificate;
+import org.apache.cloudstack.utils.security.KeyStoreUtils;
+import org.apache.log4j.Logger;
+
import com.cloud.agent.AgentManager;
import com.cloud.agent.Listener;
import com.cloud.agent.api.AgentControlAnswer;
@@ -42,17 +59,10 @@
import com.cloud.resource.ResourceStateAdapter;
import com.cloud.resource.ServerResource;
import com.cloud.resource.UnableDeleteHostException;
+import com.cloud.utils.PasswordGenerator;
+import com.cloud.utils.StringUtils;
import com.cloud.utils.ssh.SSHCmdHelper;
-import org.apache.log4j.Logger;
-
-import javax.inject.Inject;
-import javax.naming.ConfigurationException;
-import java.net.InetAddress;
-import java.net.URI;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
+import com.trilead.ssh2.Connection;
public abstract class LibvirtServerDiscoverer extends DiscovererBase implements Discoverer, Listener, ResourceStateAdapter {
private static final Logger s_logger = Logger.getLogger(LibvirtServerDiscoverer.class);
@@ -62,7 +72,9 @@
private String _kvmPublicNic;
private String _kvmGuestNic;
@Inject
- AgentManager _agentMgr;
+ private AgentManager agentMgr;
+ @Inject
+ private CAManager caManager;
@Override
public abstract Hypervisor.HypervisorType getHypervisorType();
@@ -125,6 +137,73 @@ public boolean processTimeout(long agentId, long seq) {
return false;
}
+ private void setupAgentSecurity(final Connection sshConnection, final String agentIp, final String agentHostname) {
+ if (!caManager.canProvisionCertificates()) {
+ s_logger.warn("Cannot secure agent communication because configure CA plugin cannot provision client certificate");
+ return;
+ }
+
+ if (sshConnection == null) {
+ s_logger.warn("Cannot secure agent communication because ssh connection is invalid for host ip=" + agentIp);
+ return;
+ }
+
+ Integer validityPeriod = CAManager.CertValidityPeriod.value();
+ if (validityPeriod < 1) {
+ validityPeriod = 1;
+ }
+
+ final SSHCmdHelper.SSHCmdResult keystoreSetupResult = SSHCmdHelper.sshExecuteCmdWithResult(sshConnection,
+ String.format("/usr/share/cloudstack-common/scripts/util/%s " +
+ "/etc/cloudstack/agent/agent.properties " +
+ "/etc/cloudstack/agent/%s " +
+ "%s %d " +
+ "/etc/cloudstack/agent/%s",
+ KeyStoreUtils.keyStoreSetupScript,
+ KeyStoreUtils.defaultKeystoreFile,
+ PasswordGenerator.generateRandomPassword(16),
+ validityPeriod,
+ KeyStoreUtils.defaultCsrFile));
+
+ if (!keystoreSetupResult.isSuccess()) {
+ s_logger.error("Failing, the keystore setup script failed execution on the KVM host: " + agentIp);
+ return;
+ }
+
+ final Certificate certificate = caManager.issueCertificate(keystoreSetupResult.getStdOut(), Collections.singletonList(agentHostname), Collections.singletonList(agentIp), null, null);
+ if (certificate == null || certificate.getClientCertificate() == null) {
+ s_logger.error("Failing, the configured CA plugin failed to issue certificates for KVM host agent: " + agentIp);
+ return;
+ }
+
+ final SetupCertificateCommand certificateCommand = new SetupCertificateCommand(certificate);
+ final SSHCmdHelper.SSHCmdResult setupCertResult = SSHCmdHelper.sshExecuteCmdWithResult(sshConnection,
+ String.format("/usr/share/cloudstack-common/scripts/util/%s " +
+ "/etc/cloudstack/agent/agent.properties " +
+ "/etc/cloudstack/agent/%s %s " +
+ "/etc/cloudstack/agent/%s \"%s\" " +
+ "/etc/cloudstack/agent/%s \"%s\" " +
+ "/etc/cloudstack/agent/%s \"%s\"",
+ KeyStoreUtils.keyStoreImportScript,
+ KeyStoreUtils.defaultKeystoreFile,
+ KeyStoreUtils.sshMode,
+ KeyStoreUtils.defaultCertFile,
+ certificateCommand.getEncodedCertificate(),
+ KeyStoreUtils.defaultCaCertFile,
+ certificateCommand.getEncodedCaCertificates(),
+ KeyStoreUtils.defaultPrivateKeyFile,
+ certificateCommand.getEncodedPrivateKey()));
+
+ if (setupCertResult != null && !setupCertResult.isSuccess()) {
+ s_logger.error("Failed to setup certificate in the KVM agent's keystore file, please configure manually!");
+ return;
+ }
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Succeeded to import certificate in the keystore for agent on the KVM host: " + agentIp + ". Agent secured and trusted.");
+ }
+ }
+
@Override
public Map<? extends ServerResource, Map<String, String>>
find(long dcId, Long podId, Long clusterId, URI uri, String username, String password, List<String> hostTags) throws DiscoveryException {
@@ -143,7 +222,7 @@ public boolean processTimeout(long agentId, long seq) {
s_logger.debug(msg);
return null;
}
- com.trilead.ssh2.Connection sshConnection = null;
+ Connection sshConnection = null;
String agentIp = null;
try {
@@ -162,7 +241,7 @@ public boolean processTimeout(long agentId, long seq) {
}
}
- sshConnection = new com.trilead.ssh2.Connection(agentIp, 22);
+ sshConnection = new Connection(agentIp, 22);
sshConnection.connect(null, 60000, 60000);
if (!sshConnection.authenticateWithPassword(username, password)) {
@@ -170,7 +249,7 @@ public boolean processTimeout(long agentId, long seq) {
throw new DiscoveredWithErrorException("Authentication error");
}
- if (!SSHCmdHelper.sshExecuteCmd(sshConnection, "lsmod|grep kvm", 3)) {
+ if (!SSHCmdHelper.sshExecuteCmd(sshConnection, "lsmod|grep kvm")) {
s_logger.debug("It's not a KVM enabled machine");
return null;
}
@@ -210,7 +289,9 @@ public boolean processTimeout(long agentId, long seq) {
kvmGuestNic = (kvmPublicNic != null) ? kvmPublicNic : kvmPrivateNic;
}
- String parameters = " -m " + _hostIp + " -z " + dcId + " -p " + podId + " -c " + clusterId + " -g " + guid + " -a";
+ setupAgentSecurity(sshConnection, agentIp, hostname);
+
+ String parameters = " -m " + StringUtils.shuffleCSVList(_hostIp) + " -z " + dcId + " -p " + podId + " -c " + clusterId + " -g " + guid + " -a";
parameters += " --pubNic=" + kvmPublicNic;
parameters += " --prvNic=" + kvmPrivateNic;
@@ -221,8 +302,7 @@ public boolean processTimeout(long agentId, long seq) {
if (!username.equals("root")) {
setupAgentCommand = "sudo cloudstack-setup-agent ";
}
- if (!SSHCmdHelper.sshExecuteCmd(sshConnection,
- setupAgentCommand + parameters, 3)) {
+ if (!SSHCmdHelper.sshExecuteCmd(sshConnection, setupAgentCommand + parameters)) {
s_logger.info("cloudstack agent setup command failed: "
+ setupAgentCommand + parameters);
return null;
@@ -392,7 +472,7 @@ public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForc
_resourceMgr.deleteRoutingHost(host, isForced, isForceDeleteStorage);
try {
ShutdownCommand cmd = new ShutdownCommand(ShutdownCommand.DeleteHost, null);
- _agentMgr.send(host.getId(), cmd);
+ agentMgr.send(host.getId(), cmd);
} catch (AgentUnavailableException e) {
s_logger.warn("Sending ShutdownCommand failed: ", e);
} catch (OperationTimedoutException e) {
diff --git a/server/src/com/cloud/network/ExternalDeviceUsageManagerImpl.java b/server/src/com/cloud/network/ExternalDeviceUsageManagerImpl.java
index 200b279bf92..49dc78585ab 100644
--- a/server/src/com/cloud/network/ExternalDeviceUsageManagerImpl.java
+++ b/server/src/com/cloud/network/ExternalDeviceUsageManagerImpl.java
@@ -43,6 +43,7 @@
import com.cloud.dc.dao.VlanDao;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
+import com.cloud.host.Host.Type;
import com.cloud.host.dao.HostDao;
import com.cloud.host.dao.HostDetailsDao;
import com.cloud.network.Networks.BroadcastDomainType;
@@ -68,6 +69,7 @@
import com.cloud.network.rules.LoadBalancerContainer.Scheme;
import com.cloud.network.rules.PortForwardingRuleVO;
import com.cloud.network.rules.dao.PortForwardingRulesDao;
+import com.cloud.offering.NetworkOffering;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.resource.ResourceManager;
import com.cloud.user.AccountManager;
@@ -332,6 +334,21 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
});
}
+ public boolean isNccServiceProvider(Network network) {
+ NetworkOffering networkOffering = _networkOfferingDao.findById(network.getNetworkOfferingId());
+ if(null!= networkOffering && networkOffering.getServicePackage() != null ) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ public HostVO getNetScalerControlCenterForNetwork(Network guestConfig) {
+ long zoneId = guestConfig.getDataCenterId();
+ return _hostDao.findByTypeNameAndZoneId(zoneId, "NetscalerControlCenter", Type.NetScalerControlCenter);
+ }
+
protected class ExternalDeviceNetworkUsageTask extends ManagedContextRunnable {
public ExternalDeviceNetworkUsageTask() {
@@ -400,11 +417,20 @@ protected void runExternalDeviceNetworkUsageTask() {
continue;
}
- ExternalFirewallDeviceVO fwDeviceVO = getExternalFirewallForNetwork(network);
ExternalLoadBalancerDeviceVO lbDeviceVO = getExternalLoadBalancerForNetwork(network);
- if (lbDeviceVO == null && fwDeviceVO == null) {
+ HostVO externalNcc = null;
+ boolean isNccNetwork = isNccServiceProvider(network);
+ if(isNccNetwork) {
+ externalNcc = getNetScalerControlCenterForNetwork(network);
+ }
+ ExternalFirewallDeviceVO fwDeviceVO = getExternalFirewallForNetwork(network);
+
+ if (fwDeviceVO == null) {
continue;
}
+ if(externalNcc == null && lbDeviceVO == null) {
+ return;
+ }
// Get network stats from the external firewall
ExternalNetworkResourceUsageAnswer firewallAnswer = null;
@@ -440,13 +466,17 @@ protected void runExternalDeviceNetworkUsageTask() {
// Get network stats from the external load balancer
ExternalNetworkResourceUsageAnswer lbAnswer = null;
HostVO externalLoadBalancer = null;
- if (lbDeviceVO != null) {
- externalLoadBalancer = _hostDao.findById(lbDeviceVO.getHostId());
+ if (lbDeviceVO != null || externalNcc != null) {
+ if(isNccNetwork) {
+ externalLoadBalancer = externalNcc;
+ } else {
+ externalLoadBalancer = _hostDao.findById(lbDeviceVO.getHostId());
+ }
if (externalLoadBalancer != null) {
Long lbDeviceId = new Long(externalLoadBalancer.getId());
if (!lbDeviceUsageAnswerMap.containsKey(lbDeviceId)) {
try {
- ExternalNetworkResourceUsageCommand cmd = new ExternalNetworkResourceUsageCommand();
+ ExternalNetworkResourceUsageCommand cmd = new ExternalNetworkResourceUsageCommand(network.getId());
lbAnswer = (ExternalNetworkResourceUsageAnswer)_agentMgr.easySend(externalLoadBalancer.getId(), cmd);
if (lbAnswer == null || !lbAnswer.getResult()) {
String details = (lbAnswer != null) ? lbAnswer.getDetails() : "details unavailable";
diff --git a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java
index 75267c7e0ad..1e6271de6a2 100644
--- a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java
+++ b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java
@@ -27,12 +27,13 @@
import javax.inject.Inject;
import javax.naming.ConfigurationException;
+import org.apache.log4j.Logger;
+
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.response.ExternalLoadBalancerResponse;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice;
-import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
@@ -53,6 +54,7 @@
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.Pod;
import com.cloud.dc.Vlan.VlanType;
+import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.dc.dao.VlanDao;
@@ -62,6 +64,7 @@
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.host.DetailVO;
import com.cloud.host.Host;
+import com.cloud.host.Host.Type;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.host.dao.HostDetailsDao;
@@ -89,6 +92,7 @@
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
import com.cloud.network.dao.PhysicalNetworkVO;
+import com.cloud.network.dao.VirtualRouterProviderDao;
import com.cloud.network.element.IpDeployer;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.element.StaticNatServiceProvider;
@@ -101,6 +105,7 @@
import com.cloud.network.rules.StaticNat;
import com.cloud.network.rules.StaticNatImpl;
import com.cloud.network.rules.dao.PortForwardingRulesDao;
+import com.cloud.offering.NetworkOffering;
import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.resource.ResourceManager;
@@ -108,6 +113,8 @@
import com.cloud.resource.ResourceStateAdapter;
import com.cloud.resource.ServerResource;
import com.cloud.resource.UnableDeleteHostException;
+import com.cloud.service.dao.ServiceOfferingDao;
+import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.dao.AccountDao;
@@ -126,8 +133,10 @@
import com.cloud.vm.Nic;
import com.cloud.vm.Nic.ReservationStrategy;
import com.cloud.vm.NicVO;
+import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.NicDao;
+import com.cloud.vm.dao.VMInstanceDao;
public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase implements ExternalLoadBalancerDeviceManager, ResourceStateAdapter {
@@ -191,6 +200,19 @@
protected HostPodDao _podDao = null;
@Inject
IpAddressManager _ipAddrMgr;
+ @Inject
+ protected
+ VirtualMachineManager _itMgr;
+ @Inject
+ VMInstanceDao _vmDao;
+ @Inject
+ VMTemplateDao _templateDao;
+ @Inject
+ ServiceOfferingDao _serviceOfferingDao;
+ @Inject
+ PhysicalNetworkServiceProviderDao _physicalProviderDao;
+ @Inject
+ VirtualRouterProviderDao _vrProviderDao;
private long _defaultLbCapacity;
private static final org.apache.log4j.Logger s_logger = Logger.getLogger(ExternalLoadBalancerDeviceManagerImpl.class);
@@ -864,6 +886,21 @@ private MappingNic getLoadBalancingIpNic(DataCenterVO zone, Network network, lon
return nic;
}
+ public boolean isNccServiceProvider(Network network) {
+ NetworkOffering networkOffering = _networkOfferingDao.findById(network.getNetworkOfferingId());
+ if(null!= networkOffering && networkOffering.getServicePackage() != null ) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ public HostVO getNetScalerControlCenterForNetwork(Network guestConfig) {
+ long zoneId = guestConfig.getDataCenterId();
+ return _hostDao.findByTypeNameAndZoneId(zoneId, "NetscalerControlCenter", Type.NetScalerControlCenter);
+ }
+
@Override
public boolean applyLoadBalancerRules(Network network, List<LoadBalancingRule> loadBalancingRules) throws ResourceUnavailableException {
// Find the external load balancer in this zone
@@ -874,13 +911,21 @@ public boolean applyLoadBalancerRules(Network network, List<LoadBalancingRule> l
return true;
}
- ExternalLoadBalancerDeviceVO lbDeviceVO = getExternalLoadBalancerForNetwork(network);
- if (lbDeviceVO == null) {
- s_logger.warn("There is no external load balancer device assigned to this network either network is not implement are already shutdown so just returning");
- return true;
+ HostVO externalLoadBalancer = null;
+
+ if(isNccServiceProvider(network)) {
+ externalLoadBalancer = getNetScalerControlCenterForNetwork(network);
+ } else {
+ ExternalLoadBalancerDeviceVO lbDeviceVO = getExternalLoadBalancerForNetwork(network);
+ if (lbDeviceVO == null) {
+ s_logger.warn("There is no external load balancer device assigned to this network either network is not implement are already shutdown so just returning");
+ return true;
+ } else {
+ externalLoadBalancer = _hostDao.findById(lbDeviceVO.getHostId());
+ }
}
- HostVO externalLoadBalancer = _hostDao.findById(lbDeviceVO.getHostId());
+
boolean externalLoadBalancerIsInline = _networkMgr.isNetworkInlineMode(network);
@@ -900,6 +945,16 @@ public boolean applyLoadBalancerRules(Network network, List<LoadBalancingRule> l
String algorithm = rule.getAlgorithm();
String uuid = rule.getUuid();
String srcIp = rule.getSourceIp().addr();
+ String srcIpVlan = null;
+ String srcIpGateway = null;
+ String srcIpNetmask = null;
+ Long vlanid = _networkModel.getPublicIpAddress(rule.getSourceIp().addr(), network.getDataCenterId()).getVlanId();
+ if(vlanid != null ) {
+ VlanVO publicVlan = _vlanDao.findById(vlanid);
+ srcIpVlan = publicVlan.getVlanTag();
+ srcIpGateway = publicVlan.getVlanGateway();
+ srcIpNetmask = publicVlan.getVlanNetmask();
+ }
int srcPort = rule.getSourcePortStart();
List<LbDestination> destinations = rule.getDestinations();
@@ -921,6 +976,10 @@ public boolean applyLoadBalancerRules(Network network, List<LoadBalancingRule> l
LoadBalancerTO loadBalancer =
new LoadBalancerTO(uuid, srcIp, srcPort, protocol, algorithm, revoked, false, inline, destinations, rule.getStickinessPolicies(),
rule.getHealthCheckPolicies(), rule.getLbSslCert(), rule.getLbProtocol());
+ loadBalancer.setNetworkId(network.getId());
+ loadBalancer.setSrcIpVlan(srcIpVlan);
+ loadBalancer.setSrcIpNetmask(srcIpNetmask);
+ loadBalancer.setSrcIpGateway(srcIpGateway);
if (rule.isAutoScaleConfig()) {
loadBalancer.setAutoScaleVmGroup(rule.getAutoScaleVmGroup());
}
@@ -1112,7 +1171,12 @@ public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] st
if (!(startup[0] instanceof StartupExternalLoadBalancerCommand)) {
return null;
}
- host.setType(Host.Type.ExternalLoadBalancer);
+ if(host.getName().equalsIgnoreCase("NetScalerControlCenter")) {
+ host.setType(Host.Type.NetScalerControlCenter);
+ }
+ else {
+ host.setType(Host.Type.ExternalLoadBalancer);
+ }
return host;
}
@@ -1157,13 +1221,19 @@ protected IpDeployer getIpDeployerForInlineMode(Network network) {
return null;
}
- ExternalLoadBalancerDeviceVO lbDeviceVO = getExternalLoadBalancerForNetwork(network);
- if (lbDeviceVO == null) {
- s_logger.warn("There is no external load balancer device assigned to this network either network is not implement are already shutdown so just returning");
- return null;
- }
+ HostVO externalLoadBalancer = null;
- HostVO externalLoadBalancer = _hostDao.findById(lbDeviceVO.getHostId());
+ if(isNccServiceProvider(network)) {
+ externalLoadBalancer = getNetScalerControlCenterForNetwork(network);
+ } else {
+ ExternalLoadBalancerDeviceVO lbDeviceVO = getExternalLoadBalancerForNetwork(network);
+ if (lbDeviceVO == null) {
+ s_logger.warn("There is no external load balancer device assigned to this network either network is not implement are already shutdown so just returning");
+ return null;
+ } else {
+ externalLoadBalancer = _hostDao.findById(lbDeviceVO.getHostId());
+ }
+ }
boolean externalLoadBalancerIsInline = _networkMgr.isNetworkInlineMode(network);
@@ -1211,14 +1281,11 @@ protected IpDeployer getIpDeployerForInlineMode(Network network) {
if (loadBalancersToApply.size() > 0) {
int numLoadBalancersForCommand = loadBalancersToApply.size();
LoadBalancerTO[] loadBalancersForCommand = loadBalancersToApply.toArray(new LoadBalancerTO[numLoadBalancersForCommand]);
- // LoadBalancerConfigCommand cmd = new
- // LoadBalancerConfigCommand(loadBalancersForCommand, null);
- HealthCheckLBConfigCommand cmd = new HealthCheckLBConfigCommand(loadBalancersForCommand);
+ HealthCheckLBConfigCommand cmd = new HealthCheckLBConfigCommand(loadBalancersForCommand, network.getId());
long guestVlanTag = Integer.parseInt(BroadcastDomainType.getValue(network.getBroadcastUri()));
cmd.setAccessDetail(NetworkElementCommand.GUEST_VLAN_TAG, String.valueOf(guestVlanTag));
- HealthCheckLBConfigAnswer answer = (HealthCheckLBConfigAnswer) _agentMgr
- .easySend(externalLoadBalancer.getId(), cmd);
+ HealthCheckLBConfigAnswer answer = (HealthCheckLBConfigAnswer) _agentMgr.easySend(externalLoadBalancer.getId(), cmd);
// easySend will return null on error
return answer == null ? null : answer.getLoadBalancers();
}
@@ -1240,4 +1307,5 @@ private NicVO getPlaceholderNic(Network network) {
}
return null;
}
+
}
diff --git a/server/src/com/cloud/network/IpAddressManagerImpl.java b/server/src/com/cloud/network/IpAddressManagerImpl.java
index 80684217ca5..e34f90861c3 100644
--- a/server/src/com/cloud/network/IpAddressManagerImpl.java
+++ b/server/src/com/cloud/network/IpAddressManagerImpl.java
@@ -29,8 +29,11 @@
import javax.inject.Inject;
+import org.apache.log4j.Logger;
+
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
+import org.apache.cloudstack.api.response.AcquirePodIpCmdResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.framework.config.ConfigKey;
@@ -40,7 +43,6 @@
import org.apache.cloudstack.region.PortableIpDao;
import org.apache.cloudstack.region.PortableIpVO;
import org.apache.cloudstack.region.Region;
-import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.alert.AlertManager;
@@ -50,7 +52,8 @@
import com.cloud.dc.AccountVlanMapVO;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenter.NetworkType;
-import com.cloud.dc.DomainVlanMapVO;
+import com.cloud.dc.DataCenterIpAddressVO;
+import com.cloud.dc.HostPodVO;
import com.cloud.dc.Pod;
import com.cloud.dc.PodVlanMapVO;
import com.cloud.dc.Vlan;
@@ -58,8 +61,10 @@
import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.AccountVlanMapDao;
import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.dc.dao.DataCenterIpAddressDao;
import com.cloud.dc.dao.DataCenterVnetDao;
import com.cloud.dc.dao.DomainVlanMapDao;
+import com.cloud.dc.dao.HostPodDao;
import com.cloud.dc.dao.PodVlanMapDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.deploy.DeployDestination;
@@ -279,6 +284,11 @@
PortableIpDao _portableIpDao;
@Inject
VpcDao _vpcDao;
+ @Inject
+ DataCenterIpAddressDao _privateIPAddressDao;
+ @Inject
+ HostPodDao _hpDao;
+
SearchBuilder<IPAddressVO> AssignIpAddressSearch;
SearchBuilder<IPAddressVO> AssignIpAddressFromPodVlanSearch;
@@ -401,7 +411,7 @@ public boolean configure(String name, Map<String, Object> params) {
SearchBuilder<PodVlanMapVO> podVlanMapSB = _podVlanMapDao.createSearchBuilder();
podVlanMapSB.and("podId", podVlanMapSB.entity().getPodId(), Op.EQ);
AssignIpAddressFromPodVlanSearch.join("podVlanMapSB", podVlanMapSB, podVlanMapSB.entity().getVlanDbId(), AssignIpAddressFromPodVlanSearch.entity().getVlanId(),
- JoinType.INNER);
+ JoinType.INNER);
AssignIpAddressFromPodVlanSearch.join("vlan", podVlanSearch, podVlanSearch.entity().getId(), AssignIpAddressFromPodVlanSearch.entity().getVlanId(), JoinType.INNER);
AssignIpAddressFromPodVlanSearch.done();
@@ -417,7 +427,7 @@ public boolean configure(String name, Map<String, Object> params) {
}
private IpAddress allocateIP(Account ipOwner, boolean isSystem, long zoneId) throws ResourceAllocationException, InsufficientAddressCapacityException,
- ConcurrentOperationException {
+ ConcurrentOperationException {
Account caller = CallContext.current().getCallingAccount();
long callerUserId = CallContext.current().getCallingUserId();
// check permissions
@@ -492,7 +502,7 @@ boolean checkIfIpAssocRequired(Network network, boolean postApplyRules, List<Pub
@Override
public boolean applyRules(List<? extends FirewallRule> rules, FirewallRule.Purpose purpose, NetworkRuleApplier applier, boolean continueOnError)
- throws ResourceUnavailableException {
+ throws ResourceUnavailableException {
if (rules == null || rules.size() == 0) {
s_logger.debug("There are no rules to forward to the network elements");
return true;
@@ -641,21 +651,21 @@ public boolean releasePortableIpAddress(final long addrId) {
return Transaction.execute(new TransactionCallback<Boolean>() {
@Override
public Boolean doInTransaction(TransactionStatus status) {
- portableIpLock.lock(5);
- IPAddressVO ip = _ipAddressDao.findById(addrId);
+ portableIpLock.lock(5);
+ IPAddressVO ip = _ipAddressDao.findById(addrId);
- // unassign portable IP
- PortableIpVO portableIp = _portableIpDao.findByIpAddress(ip.getAddress().addr());
- _portableIpDao.unassignIpAddress(portableIp.getId());
+ // unassign portable IP
+ PortableIpVO portableIp = _portableIpDao.findByIpAddress(ip.getAddress().addr());
+ _portableIpDao.unassignIpAddress(portableIp.getId());
- // removed the provisioned vlan
- VlanVO vlan = _vlanDao.findById(ip.getVlanId());
- _vlanDao.remove(vlan.getId());
+ // removed the provisioned vlan
+ VlanVO vlan = _vlanDao.findById(ip.getVlanId());
+ _vlanDao.remove(vlan.getId());
- // remove the provisioned public ip address
- _ipAddressDao.remove(ip.getId());
+ // remove the provisioned public ip address
+ _ipAddressDao.remove(ip.getId());
- return true;
+ return true;
}
});
} finally {
@@ -665,20 +675,20 @@ public Boolean doInTransaction(TransactionStatus status) {
@Override
public PublicIp assignPublicIpAddress(long dcId, Long podId, Account owner, VlanType type, Long networkId, String requestedIp, boolean isSystem)
- throws InsufficientAddressCapacityException {
+ throws InsufficientAddressCapacityException {
return fetchNewPublicIp(dcId, podId, null, owner, type, networkId, false, true, requestedIp, isSystem, null, null);
}
@Override
public PublicIp assignPublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List<Long> vlanDbIds, Long networkId, String requestedIp, boolean isSystem)
- throws InsufficientAddressCapacityException {
+ throws InsufficientAddressCapacityException {
return fetchNewPublicIp(dcId, podId, vlanDbIds, owner, type, networkId, false, true, requestedIp, isSystem, null, null);
}
@DB
public PublicIp fetchNewPublicIp(final long dcId, final Long podId, final List<Long> vlanDbIds, final Account owner, final VlanType vlanUse, final Long guestNetworkId,
final boolean sourceNat, final boolean assign, final String requestedIp, final boolean isSystem, final Long vpcId, final Boolean displayIp)
- throws InsufficientAddressCapacityException {
+ throws InsufficientAddressCapacityException {
IPAddressVO addr = Transaction.execute(new TransactionCallbackWithException<IPAddressVO, InsufficientAddressCapacityException>() {
@Override
public IPAddressVO doInTransaction(TransactionStatus status) throws InsufficientAddressCapacityException {
@@ -709,11 +719,6 @@ public IPAddressVO doInTransaction(TransactionStatus status) throws Insufficient
dedicatedVlanDbIds.add(map.getVlanDbId());
}
}
- List<DomainVlanMapVO> domainMaps = _domainVlanMapDao.listDomainVlanMapsByDomain(owner.getDomainId());
- for (DomainVlanMapVO map : domainMaps) {
- if (vlanDbIds == null || vlanDbIds.contains(map.getVlanDbId()))
- dedicatedVlanDbIds.add(map.getVlanDbId());
- }
List<VlanVO> nonDedicatedVlans = _vlanDao.listZoneWideNonDedicatedVlans(dcId);
for (VlanVO nonDedicatedVlan : nonDedicatedVlans) {
if (vlanDbIds == null || vlanDbIds.contains(nonDedicatedVlan.getId()))
@@ -722,10 +727,10 @@ public IPAddressVO doInTransaction(TransactionStatus status) throws Insufficient
if (dedicatedVlanDbIds != null && !dedicatedVlanDbIds.isEmpty()) {
fetchFromDedicatedRange = true;
sc.setParameters("vlanId", dedicatedVlanDbIds.toArray());
- errorMessage.append(", vlanId id=" + Arrays.toString(dedicatedVlanDbIds.toArray()));
+ errorMessage.append(", vlanId id=" + Arrays.toString(dedicatedVlanDbIds.toArray()));
} else if (nonDedicatedVlanDbIds != null && !nonDedicatedVlanDbIds.isEmpty()) {
sc.setParameters("vlanId", nonDedicatedVlanDbIds.toArray());
- errorMessage.append(", vlanId id=" + Arrays.toString(nonDedicatedVlanDbIds.toArray()));
+ errorMessage.append(", vlanId id=" + Arrays.toString(nonDedicatedVlanDbIds.toArray()));
} else {
if (podId != null) {
InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Insufficient address capacity", Pod.class, podId);
@@ -763,7 +768,7 @@ public IPAddressVO doInTransaction(TransactionStatus status) throws Insufficient
if (useSystemIps && nonDedicatedVlanDbIds != null && !nonDedicatedVlanDbIds.isEmpty()) {
fetchFromDedicatedRange = false;
sc.setParameters("vlanId", nonDedicatedVlanDbIds.toArray());
- errorMessage.append(", vlanId id=" + Arrays.toString(nonDedicatedVlanDbIds.toArray()));
+ errorMessage.append(", vlanId id=" + Arrays.toString(nonDedicatedVlanDbIds.toArray()));
addrs = _ipAddressDao.lockRows(sc, filter, true);
}
}
@@ -781,7 +786,7 @@ public IPAddressVO doInTransaction(TransactionStatus status) throws Insufficient
throw ex;
}
- assert (addrs.size() == 1) : "Return size is incorrect: " + addrs.size();
+ assert(addrs.size() == 1) : "Return size is incorrect: " + addrs.size();
if (!fetchFromDedicatedRange && VlanType.VirtualNetwork.equals(vlanUse)) {
// Check that the maximum number of public IPs for the given accountId will not be exceeded
@@ -835,29 +840,30 @@ public void markPublicIpAsAllocated(final IPAddressVO addr) {
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
- Account owner = _accountMgr.getAccount(addr.getAllocatedToAccountId());
- synchronized (this) {
- if (_ipAddressDao.lockRow(addr.getId(),true) != null) {
- IPAddressVO userIp = _ipAddressDao.findById(addr.getId());
- if (userIp.getState() == IpAddress.State.Allocating || addr.getState() == IpAddress.State.Free) {
- addr.setState(IpAddress.State.Allocated);
- _ipAddressDao.update(addr.getId(), addr);
- // Save usage event
- if (owner.getAccountId() != Account.ACCOUNT_ID_SYSTEM) {
- VlanVO vlan = _vlanDao.findById(addr.getVlanId());
- String guestType = vlan.getVlanType().toString();
- if (!isIpDedicated(addr)) {
- UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_IP_ASSIGN, owner.getId(), addr.getDataCenterId(), addr.getId(), addr.getAddress().toString(),
- addr.isSourceNat(), guestType, addr.getSystem(), addr.getClass().getName(), addr.getUuid());
- }
- if (updateIpResourceCount(addr)) {
- _resourceLimitMgr.incrementResourceCount(owner.getId(), ResourceType.public_ip);
+ Account owner = _accountMgr.getAccount(addr.getAllocatedToAccountId());
+ synchronized (this) {
+ if (_ipAddressDao.lockRow(addr.getId(), true) != null) {
+ IPAddressVO userIp = _ipAddressDao.findById(addr.getId());
+ if (userIp.getState() == IpAddress.State.Allocating || addr.getState() == IpAddress.State.Free) {
+ addr.setState(IpAddress.State.Allocated);
+ _ipAddressDao.update(addr.getId(), addr);
+ // Save usage event
+ if (owner.getAccountId() != Account.ACCOUNT_ID_SYSTEM) {
+ VlanVO vlan = _vlanDao.findById(addr.getVlanId());
+ String guestType = vlan.getVlanType().toString();
+ if (!isIpDedicated(addr)) {
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_IP_ASSIGN, owner.getId(), addr.getDataCenterId(), addr.getId(),
+ addr.getAddress().toString(),
+ addr.isSourceNat(), guestType, addr.getSystem(), addr.getClass().getName(), addr.getUuid());
+ }
+ if (updateIpResourceCount(addr)) {
+ _resourceLimitMgr.incrementResourceCount(owner.getId(), ResourceType.public_ip);
+ }
}
}
}
}
}
- }
});
}
@@ -870,8 +876,8 @@ private boolean isIpDedicated(IPAddressVO addr) {
@Override
public PublicIp assignSourceNatIpAddressToGuestNetwork(Account owner, Network guestNetwork) throws InsufficientAddressCapacityException, ConcurrentOperationException {
- assert (guestNetwork.getTrafficType() != null) : "You're asking for a source nat but your network "
- + "can't participate in source nat. What do you have to say for yourself?";
+ assert(guestNetwork.getTrafficType() != null) : "You're asking for a source nat but your network "
+ + "can't participate in source nat. What do you have to say for yourself?";
long dcId = guestNetwork.getDataCenterId();
IPAddressVO sourceNatIp = getExistingSourceNatInNetwork(owner.getId(), guestNetwork.getId());
@@ -900,15 +906,15 @@ public PublicIp assignDedicateIpAddress(Account owner, final Long guestNtwkId, f
public PublicIp doInTransaction(TransactionStatus status) throws InsufficientAddressCapacityException {
Account owner = _accountDao.acquireInLockTable(ownerId);
- if (owner == null) {
- // this ownerId comes from owner or type Account. See the class "AccountVO" and the annotations in that class
- // to get the table name and field name that is queried to fill this ownerid.
- ConcurrentOperationException ex = new ConcurrentOperationException("Unable to lock account");
- throw ex;
- }
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("lock account " + ownerId + " is acquired");
- }
+ if (owner == null) {
+ // this ownerId comes from owner or type Account. See the class "AccountVO" and the annotations in that class
+ // to get the table name and field name that is queried to fill this ownerid.
+ ConcurrentOperationException ex = new ConcurrentOperationException("Unable to lock account");
+ throw ex;
+ }
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("lock account " + ownerId + " is acquired");
+ }
boolean displayIp = true;
if (guestNtwkId != null) {
Network ntwk = _networksDao.findById(guestNtwkId);
@@ -919,10 +925,10 @@ public PublicIp doInTransaction(TransactionStatus status) throws InsufficientAdd
}
PublicIp ip = fetchNewPublicIp(dcId, null, null, owner, VlanType.VirtualNetwork, guestNtwkId, isSourceNat, false, null, false, vpcId, displayIp);
- IPAddressVO publicIp = ip.ip();
+ IPAddressVO publicIp = ip.ip();
- markPublicIpAsAllocated(publicIp);
- _ipAddressDao.update(publicIp.getId(), publicIp);
+ markPublicIpAsAllocated(publicIp);
+ _ipAddressDao.update(publicIp.getId(), publicIp);
return ip;
}
@@ -974,7 +980,7 @@ public boolean applyIpAssociations(Network network, boolean continueOnError) thr
// but still be associated with the account. Its up to caller of this function to decide when to invoke IPAssociation
@Override
public boolean applyIpAssociations(Network network, boolean postApplyRules, boolean continueOnError, List<? extends PublicIpAddress> publicIps)
- throws ResourceUnavailableException {
+ throws ResourceUnavailableException {
boolean success = true;
Map<PublicIpAddress, Set<Service>> ipToServices = _networkModel.getIpToServices(publicIps, postApplyRules, true);
@@ -1016,11 +1022,77 @@ public boolean applyIpAssociations(Network network, boolean postApplyRules, bool
return success;
}
+ @DB
+ @Override
+ public AcquirePodIpCmdResponse allocatePodIp(String zoneId, String podId) throws ConcurrentOperationException, ResourceAllocationException {
+
+ DataCenter zone = _entityMgr.findByUuid(DataCenter.class, zoneId);
+ Account caller = CallContext.current().getCallingAccount();
+ if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getId())) {
+ ResourceAllocationException ex = new ResourceAllocationException("Cannot perform this operation, " + "Zone is currently disabled" + "zoneId=" + zone.getUuid(),
+ ResourceType.network);
+ throw ex;
+ }
+
+ DataCenterIpAddressVO vo = null;
+ if (podId == null)
+ throw new ResourceAllocationException("Please do not provide NULL podId", ResourceType.network);
+ HostPodVO podvo = null;
+ podvo = _hpDao.findByUuid(podId);
+ if (podvo == null)
+ throw new ResourceAllocationException("No sush pod exists", ResourceType.network);
+
+ vo = _privateIPAddressDao.takeIpAddress(zone.getId(), podvo.getId(), 0, caller.getId() + "");
+ if(vo == null)
+ throw new ResourceAllocationException("Unable to allocate IP from this Pod", ResourceType.network);
+ if (vo.getIpAddress() == null)
+ throw new ResourceAllocationException("Unable to allocate IP from this Pod", ResourceType.network);
+
+ HostPodVO pod_vo = _hpDao.findById(vo.getPodId());
+ AcquirePodIpCmdResponse ret = new AcquirePodIpCmdResponse();
+ ret.setCidrAddress(pod_vo.getCidrAddress());
+ ret.setGateway(pod_vo.getGateway());
+ ret.setInstanceId(vo.getInstanceId());
+ ret.setIpAddress(vo.getIpAddress());
+ ret.setMacAddress(vo.getMacAddress());
+ ret.setPodId(vo.getPodId());
+ ret.setId(vo.getId());
+
+ return ret;
+ }
+
+ @DB
+ @Override
+ public void releasePodIp(Long id) throws CloudRuntimeException {
+
+ // Verify input parameters
+ DataCenterIpAddressVO ipVO = _privateIPAddressDao.findById(id);
+ if (ipVO == null) {
+ throw new CloudRuntimeException("Unable to find ip address by id:" + id);
+ }
+
+ if (ipVO.getTakenAt() == null) {
+ s_logger.debug("Ip Address with id= " + id + " is not allocated, so do nothing.");
+ throw new CloudRuntimeException("Ip Address with id= " + id + " is not allocated, so do nothing.");
+ }
+ // Verify permission
+ DataCenter zone = _entityMgr.findById(DataCenter.class, ipVO.getDataCenterId());
+ Account caller = CallContext.current().getCallingAccount();
+ if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getId())) {
+ throw new CloudRuntimeException("Cannot perform this operation, " + "Zone is currently disabled" + "zoneId=" + ipVO.getDataCenterId());
+ }
+ try {
+ _privateIPAddressDao.releasePodIpAddress(id);
+ } catch (Exception e) {
+ new CloudRuntimeException(e.getMessage());
+ }
+ }
+
@DB
@Override
public IpAddress allocateIp(final Account ipOwner, final boolean isSystem, Account caller, long callerUserId, final DataCenter zone, final Boolean displayIp)
throws ConcurrentOperationException,
- ResourceAllocationException, InsufficientAddressCapacityException {
+ ResourceAllocationException, InsufficientAddressCapacityException {
final VlanType vlanType = VlanType.VirtualNetwork;
final boolean assign = false;
@@ -1054,16 +1126,17 @@ public IpAddress allocateIp(final Account ipOwner, final boolean isSystem, Accou
public PublicIp doInTransaction(TransactionStatus status) throws InsufficientAddressCapacityException {
PublicIp ip = fetchNewPublicIp(zone.getId(), null, null, ipOwner, vlanType, null, false, assign, null, isSystem, null, displayIp);
- if (ip == null) {
+ if (ip == null) {
InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Unable to find available public IP addresses", DataCenter.class, zone
.getId());
- ex.addProxyObject(ApiDBUtils.findZoneById(zone.getId()).getUuid());
- throw ex;
- }
- CallContext.current().setEventDetails("Ip Id: " + ip.getId());
- Ip ipAddress = ip.getAddress();
+ ex.addProxyObject(ApiDBUtils.findZoneById(zone.getId()).getUuid());
+ throw ex;
- s_logger.debug("Got " + ipAddress + " to assign for account " + ipOwner.getId() + " in zone " + zone.getId());
+ }
+ CallContext.current().setEventDetails("Ip Id: " + ip.getId());
+ Ip ipAddress = ip.getAddress();
+
+ s_logger.debug("Got " + ipAddress + " to assign for account " + ipOwner.getId() + " in zone " + zone.getId());
return ip;
}
@@ -1098,40 +1171,40 @@ public IpAddress allocatePortableIp(final Account ipOwner, Account caller, final
public IPAddressVO doInTransaction(TransactionStatus status) throws InsufficientAddressCapacityException {
PortableIpVO allocatedPortableIp;
- List<PortableIpVO> portableIpVOs = _portableIpDao.listByRegionIdAndState(1, PortableIp.State.Free);
- if (portableIpVOs == null || portableIpVOs.isEmpty()) {
+ List<PortableIpVO> portableIpVOs = _portableIpDao.listByRegionIdAndState(1, PortableIp.State.Free);
+ if (portableIpVOs == null || portableIpVOs.isEmpty()) {
InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Unable to find available portable IP addresses", Region.class,
new Long(1));
- throw ex;
- }
+ throw ex;
+ }
- // allocate first portable IP to the user
- allocatedPortableIp = portableIpVOs.get(0);
- allocatedPortableIp.setAllocatedTime(new Date());
- allocatedPortableIp.setAllocatedToAccountId(ipOwner.getAccountId());
- allocatedPortableIp.setAllocatedInDomainId(ipOwner.getDomainId());
- allocatedPortableIp.setState(PortableIp.State.Allocated);
- _portableIpDao.update(allocatedPortableIp.getId(), allocatedPortableIp);
-
- // To make portable IP available as a zone level resource we need to emulate portable IP's (which are
- // provisioned at region level) as public IP provisioned in a zone. user_ip_address and vlan combo give the
- // identity of a public IP in zone. Create entry for portable ip in these tables.
-
- // provision portable IP range VLAN into the zone
- long physicalNetworkId = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(dcId, TrafficType.Public).getId();
- Network network = _networkModel.getSystemNetworkByZoneAndTrafficType(dcId, TrafficType.Public);
- String range = allocatedPortableIp.getAddress() + "-" + allocatedPortableIp.getAddress();
+ // allocate first portable IP to the user
+ allocatedPortableIp = portableIpVOs.get(0);
+ allocatedPortableIp.setAllocatedTime(new Date());
+ allocatedPortableIp.setAllocatedToAccountId(ipOwner.getAccountId());
+ allocatedPortableIp.setAllocatedInDomainId(ipOwner.getDomainId());
+ allocatedPortableIp.setState(PortableIp.State.Allocated);
+ _portableIpDao.update(allocatedPortableIp.getId(), allocatedPortableIp);
+
+ // To make portable IP available as a zone level resource we need to emulate portable IP's (which are
+ // provisioned at region level) as public IP provisioned in a zone. user_ip_address and vlan combo give the
+ // identity of a public IP in zone. Create entry for portable ip in these tables.
+
+ // provision portable IP range VLAN into the zone
+ long physicalNetworkId = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(dcId, TrafficType.Public).getId();
+ Network network = _networkModel.getSystemNetworkByZoneAndTrafficType(dcId, TrafficType.Public);
+ String range = allocatedPortableIp.getAddress() + "-" + allocatedPortableIp.getAddress();
VlanVO vlan = new VlanVO(VlanType.VirtualNetwork, allocatedPortableIp.getVlan(), allocatedPortableIp.getGateway(), allocatedPortableIp.getNetmask(), dcId,
range, network.getId(), physicalNetworkId, null, null, null);
- vlan = _vlanDao.persist(vlan);
+ vlan = _vlanDao.persist(vlan);
- // provision the portable IP in to user_ip_address table
+ // provision the portable IP in to user_ip_address table
IPAddressVO ipaddr = new IPAddressVO(new Ip(allocatedPortableIp.getAddress()), dcId, networkId, vpcID, physicalNetworkId, network.getId(), vlan.getId(), true);
- ipaddr.setState(State.Allocated);
- ipaddr.setAllocatedTime(new Date());
- ipaddr.setAllocatedInDomainId(ipOwner.getDomainId());
- ipaddr.setAllocatedToAccountId(ipOwner.getId());
- ipaddr = _ipAddressDao.persist(ipaddr);
+ ipaddr.setState(State.Allocated);
+ ipaddr.setAllocatedTime(new Date());
+ ipaddr.setAllocatedInDomainId(ipOwner.getDomainId());
+ ipaddr.setAllocatedToAccountId(ipOwner.getId());
+ ipaddr = _ipAddressDao.persist(ipaddr);
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_PORTABLE_IP_ASSIGN, ipaddr.getId(), ipaddr.getDataCenterId(), ipaddr.getId(),
ipaddr.getAddress().toString(), ipaddr.isSourceNat(), null, ipaddr.getSystem(), ipaddr.getClass().getName(), ipaddr.getUuid());
@@ -1168,7 +1241,7 @@ protected IPAddressVO getExistingSourceNatInNetwork(long ownerId, Long networkId
}
}
- assert (sourceNatIp != null) : "How do we get a bunch of ip addresses but none of them are source nat? " + "account=" + ownerId + "; networkId=" + networkId;
+ assert(sourceNatIp != null) : "How do we get a bunch of ip addresses but none of them are source nat? " + "account=" + ownerId + "; networkId=" + networkId;
}
return sourceNatIp;
@@ -1177,7 +1250,7 @@ protected IPAddressVO getExistingSourceNatInNetwork(long ownerId, Long networkId
@DB
@Override
public IPAddressVO associateIPToGuestNetwork(long ipId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException, ResourceUnavailableException,
- InsufficientAddressCapacityException, ConcurrentOperationException {
+ InsufficientAddressCapacityException, ConcurrentOperationException {
Account caller = CallContext.current().getCallingAccount();
Account owner = null;
@@ -1196,7 +1269,7 @@ public IPAddressVO associateIPToGuestNetwork(long ipId, long networkId, boolean
network);
} else {
throw new InvalidParameterValueException("IP can be associated with guest network of 'shared' type only if "
- + "network services Source Nat, Static Nat, Port Forwarding, Load balancing, firewall are enabled in the network");
+ + "network services Source Nat, Static Nat, Port Forwarding, Load balancing, firewall are enabled in the network");
}
}
} else {
@@ -1307,7 +1380,7 @@ protected boolean isSharedNetworkOfferingWithServices(long networkOfferingId) {
|| _networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.StaticNat)
|| _networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.Firewall)
|| _networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.PortForwarding) || _networkModel.areServicesSupportedByNetworkOffering(
- networkOfferingId, Service.Lb))) {
+ networkOfferingId, Service.Lb))) {
return true;
}
return false;
@@ -1315,14 +1388,14 @@ protected boolean isSharedNetworkOfferingWithServices(long networkOfferingId) {
@Override
public IPAddressVO associatePortableIPToGuestNetwork(long ipAddrId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException, ResourceUnavailableException,
- InsufficientAddressCapacityException, ConcurrentOperationException {
+ InsufficientAddressCapacityException, ConcurrentOperationException {
return associateIPToGuestNetwork(ipAddrId, networkId, releaseOnFailure);
}
@DB
@Override
public IPAddressVO disassociatePortableIPToGuestNetwork(long ipId, long networkId) throws ResourceAllocationException, ResourceUnavailableException,
- InsufficientAddressCapacityException, ConcurrentOperationException {
+ InsufficientAddressCapacityException, ConcurrentOperationException {
Account caller = CallContext.current().getCallingAccount();
Account owner = null;
@@ -1346,7 +1419,7 @@ public IPAddressVO disassociatePortableIPToGuestNetwork(long ipId, long networkI
DataCenter zone = _entityMgr.findById(DataCenter.class, network.getDataCenterId());
if (zone.getNetworkType() == NetworkType.Advanced) {
if (network.getGuestType() == Network.GuestType.Shared) {
- assert (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId()));
+ assert(isSharedNetworkOfferingWithServices(network.getNetworkOfferingId()));
_accountMgr.checkAccess(CallContext.current().getCallingAccount(), AccessType.UseEntry, false,
network);
}
@@ -1430,7 +1503,7 @@ public boolean isPortableIpTransferableFromNetwork(long ipAddrId, long networkId
@DB
@Override
public void transferPortableIP(final long ipAddrId, long currentNetworkId, long newNetworkId) throws ResourceAllocationException, ResourceUnavailableException,
- InsufficientAddressCapacityException, ConcurrentOperationException {
+ InsufficientAddressCapacityException, ConcurrentOperationException {
Network srcNetwork = _networksDao.findById(currentNetworkId);
if (srcNetwork == null) {
@@ -1447,7 +1520,7 @@ public void transferPortableIP(final long ipAddrId, long currentNetworkId, long
throw new InvalidParameterValueException("Invalid portable ip address id is given");
}
- assert (isPortableIpTransferableFromNetwork(ipAddrId, currentNetworkId));
+ assert(isPortableIpTransferableFromNetwork(ipAddrId, currentNetworkId));
// disassociate portable IP with current network/VPC network
if (srcNetwork.getVpcId() != null) {
@@ -1462,19 +1535,19 @@ public void transferPortableIP(final long ipAddrId, long currentNetworkId, long
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
- long physicalNetworkId = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(dstNetwork.getDataCenterId(), TrafficType.Public).getId();
- long publicNetworkId = _networkModel.getSystemNetworkByZoneAndTrafficType(dstNetwork.getDataCenterId(), TrafficType.Public).getId();
-
- ip.setDataCenterId(dstNetwork.getDataCenterId());
- ip.setPhysicalNetworkId(physicalNetworkId);
- ip.setSourceNetworkId(publicNetworkId);
- _ipAddressDao.update(ipAddrId, ip);
-
- VlanVO vlan = _vlanDao.findById(ip.getVlanId());
- vlan.setPhysicalNetworkId(physicalNetworkId);
- vlan.setNetworkId(publicNetworkId);
- vlan.setDataCenterId(dstNetwork.getDataCenterId());
- _vlanDao.update(ip.getVlanId(), vlan);
+ long physicalNetworkId = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(dstNetwork.getDataCenterId(), TrafficType.Public).getId();
+ long publicNetworkId = _networkModel.getSystemNetworkByZoneAndTrafficType(dstNetwork.getDataCenterId(), TrafficType.Public).getId();
+
+ ip.setDataCenterId(dstNetwork.getDataCenterId());
+ ip.setPhysicalNetworkId(physicalNetworkId);
+ ip.setSourceNetworkId(publicNetworkId);
+ _ipAddressDao.update(ipAddrId, ip);
+
+ VlanVO vlan = _vlanDao.findById(ip.getVlanId());
+ vlan.setPhysicalNetworkId(physicalNetworkId);
+ vlan.setNetworkId(publicNetworkId);
+ vlan.setDataCenterId(dstNetwork.getDataCenterId());
+ _vlanDao.update(ip.getVlanId(), vlan);
}
});
}
@@ -1483,22 +1556,24 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
associatePortableIPToGuestNetwork(ipAddrId, newNetworkId, false);
Transaction.execute(new TransactionCallbackNoReturn() {
+
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
- if (dstNetwork.getVpcId() != null) {
- ip.setVpcId(dstNetwork.getVpcId());
- } else {
- ip.setVpcId(null);
- }
+ if (dstNetwork.getVpcId() != null) {
+ ip.setVpcId(dstNetwork.getVpcId());
+ } else {
+ ip.setVpcId(null);
+ }
- _ipAddressDao.update(ipAddrId, ip);
+ _ipAddressDao.update(ipAddrId, ip);
}
+
});
// trigger an action event for the transfer of portable IP across the networks, so that external entities
// monitoring for this event can initiate the route advertisement for the availability of IP from the zoe
ActionEventUtils.onActionEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, Domain.ROOT_DOMAIN, EventTypes.EVENT_PORTABLE_IP_TRANSFER,
- "Portable IP associated is transferred from network " + currentNetworkId + " to " + newNetworkId);
+ "Portable IP associated is transferred from network " + currentNetworkId + " to " + newNetworkId);
}
protected List<? extends Network> getIsolatedNetworksWithSourceNATOwnedByAccountInZone(long zoneId, Account owner) {
@@ -1525,30 +1600,30 @@ public boolean associateIpAddressListToAccount(long userId, final long accountId
boolean createNetwork = false;
Network guestNetwork = guestNetworkFinal;
- if (guestNetwork == null) {
- List<? extends Network> networks = getIsolatedNetworksWithSourceNATOwnedByAccountInZone(zoneId, owner);
- if (networks.size() == 0) {
- createNetwork = true;
- } else if (networks.size() == 1) {
- guestNetwork = networks.get(0);
- } else {
- throw new InvalidParameterValueException("Error, more than 1 Guest Isolated Networks with SourceNAT "
- + "service enabled found for this account, cannot assosiate the IP range, please provide the network ID");
- }
- }
+ if (guestNetwork == null) {
+ List<? extends Network> networks = getIsolatedNetworksWithSourceNATOwnedByAccountInZone(zoneId, owner);
+ if (networks.size() == 0) {
+ createNetwork = true;
+ } else if (networks.size() == 1) {
+ guestNetwork = networks.get(0);
+ } else {
+ throw new InvalidParameterValueException("Error, more than 1 Guest Isolated Networks with SourceNAT "
+ + "service enabled found for this account, cannot assosiate the IP range, please provide the network ID");
+ }
+ }
- // create new Virtual network (Isolated with SourceNAT) for the user if it doesn't exist
- List<NetworkOfferingVO> requiredOfferings = _networkOfferingDao.listByAvailability(Availability.Required, false);
- if (requiredOfferings.size() < 1) {
+ // create new Virtual network (Isolated with SourceNAT) for the user if it doesn't exist
+ List<NetworkOfferingVO> requiredOfferings = _networkOfferingDao.listByAvailability(Availability.Required, false);
+ if (requiredOfferings.size() < 1) {
throw new CloudRuntimeException("Unable to find network offering with availability=" + Availability.Required
+ " to automatically create the network as part of createVlanIpRange");
- }
- if (createNetwork) {
- if (requiredOfferings.get(0).getState() == NetworkOffering.State.Enabled) {
- long physicalNetworkId = _networkModel.findPhysicalNetworkId(zoneId, requiredOfferings.get(0).getTags(), requiredOfferings.get(0).getTrafficType());
- // Validate physical network
- PhysicalNetwork physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId);
- if (physicalNetwork == null) {
+ }
+ if (createNetwork) {
+ if (requiredOfferings.get(0).getState() == NetworkOffering.State.Enabled) {
+ long physicalNetworkId = _networkModel.findPhysicalNetworkId(zoneId, requiredOfferings.get(0).getTags(), requiredOfferings.get(0).getTrafficType());
+ // Validate physical network
+ PhysicalNetwork physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId);
+ if (physicalNetwork == null) {
throw new InvalidParameterValueException("Unable to find physical network with id: " + physicalNetworkId + " and tag: "
+ requiredOfferings.get(0).getTags());
}
@@ -1556,45 +1631,45 @@ public boolean associateIpAddressListToAccount(long userId, final long accountId
s_logger.debug("Creating network for account " + owner + " from the network offering id=" + requiredOfferings.get(0).getId()
+ " as a part of createVlanIpRange process");
guestNetwork = _networkMgr.createGuestNetwork(requiredOfferings.get(0).getId(), owner.getAccountName() + "-network", owner.getAccountName()
- + "-network", null, null, null, null, owner, null, physicalNetwork, zoneId, ACLType.Account, null, null, null, null, true, null);
- if (guestNetwork == null) {
- s_logger.warn("Failed to create default Virtual network for the account " + accountId + "in zone " + zoneId);
+ + "-network", null, null, null, false, null, owner, null, physicalNetwork, zoneId, ACLType.Account, null, null, null, null, true, null);
+ if (guestNetwork == null) {
+ s_logger.warn("Failed to create default Virtual network for the account " + accountId + "in zone " + zoneId);
throw new CloudRuntimeException("Failed to create a Guest Isolated Networks with SourceNAT "
+ "service enabled as a part of createVlanIpRange, for the account " + accountId + "in zone " + zoneId);
- }
- } else {
- throw new CloudRuntimeException("Required network offering id=" + requiredOfferings.get(0).getId() + " is not in " + NetworkOffering.State.Enabled);
- }
- }
+ }
+ } else {
+ throw new CloudRuntimeException("Required network offering id=" + requiredOfferings.get(0).getId() + " is not in " + NetworkOffering.State.Enabled);
+ }
+ }
- // Check if there is a source nat ip address for this account; if not - we have to allocate one
- boolean allocateSourceNat = false;
- List<IPAddressVO> sourceNat = _ipAddressDao.listByAssociatedNetwork(guestNetwork.getId(), true);
- if (sourceNat.isEmpty()) {
- allocateSourceNat = true;
- }
+ // Check if there is a source nat ip address for this account; if not - we have to allocate one
+ boolean allocateSourceNat = false;
+ List<IPAddressVO> sourceNat = _ipAddressDao.listByAssociatedNetwork(guestNetwork.getId(), true);
+ if (sourceNat.isEmpty()) {
+ allocateSourceNat = true;
+ }
- // update all ips with a network id, mark them as allocated and update resourceCount/usage
- List<IPAddressVO> ips = _ipAddressDao.listByVlanId(vlanId);
- boolean isSourceNatAllocated = false;
- for (IPAddressVO addr : ips) {
- if (addr.getState() != State.Allocated) {
- if (!isSourceNatAllocated && allocateSourceNat) {
- addr.setSourceNat(true);
- isSourceNatAllocated = true;
- } else {
- addr.setSourceNat(false);
- }
- addr.setAssociatedWithNetworkId(guestNetwork.getId());
- addr.setVpcId(guestNetwork.getVpcId());
- addr.setAllocatedTime(new Date());
- addr.setAllocatedInDomainId(owner.getDomainId());
- addr.setAllocatedToAccountId(owner.getId());
- addr.setSystem(false);
- addr.setState(IpAddress.State.Allocating);
- markPublicIpAsAllocated(addr);
- }
- }
+ // update all ips with a network id, mark them as allocated and update resourceCount/usage
+ List<IPAddressVO> ips = _ipAddressDao.listByVlanId(vlanId);
+ boolean isSourceNatAllocated = false;
+ for (IPAddressVO addr : ips) {
+ if (addr.getState() != State.Allocated) {
+ if (!isSourceNatAllocated && allocateSourceNat) {
+ addr.setSourceNat(true);
+ isSourceNatAllocated = true;
+ } else {
+ addr.setSourceNat(false);
+ }
+ addr.setAssociatedWithNetworkId(guestNetwork.getId());
+ addr.setVpcId(guestNetwork.getVpcId());
+ addr.setAllocatedTime(new Date());
+ addr.setAllocatedInDomainId(owner.getDomainId());
+ addr.setAllocatedToAccountId(owner.getId());
+ addr.setSystem(false);
+ addr.setState(IpAddress.State.Allocating);
+ markPublicIpAsAllocated(addr);
+ }
+ }
return new Ternary<Boolean, List<NetworkOfferingVO>, Network>(createNetwork, requiredOfferings, guestNetwork);
}
});
@@ -1629,7 +1704,7 @@ public boolean associateIpAddressListToAccount(long userId, final long accountId
} catch (Exception ex) {
s_logger.warn("Failed to implement network " + guestNetwork + " elements and resources as a part of" + " network provision due to ", ex);
CloudRuntimeException e = new CloudRuntimeException("Failed to implement network (with specified id)"
- + " elements and resources as a part of network provision for persistent network");
+ + " elements and resources as a part of network provision for persistent network");
e.addProxyObject(guestNetwork.getUuid(), "networkId");
throw e;
}
@@ -1652,20 +1727,20 @@ public IPAddressVO markIpAsUnavailable(final long addrId) {
@Override
public IPAddressVO doInTransaction(TransactionStatus status) {
if (updateIpResourceCount(ip)) {
- _resourceLimitMgr.decrementResourceCount(_ipAddressDao.findById(addrId).getAllocatedToAccountId(), ResourceType.public_ip);
- }
+ _resourceLimitMgr.decrementResourceCount(_ipAddressDao.findById(addrId).getAllocatedToAccountId(), ResourceType.public_ip);
+ }
- // Save usage event
- if (ip.getAllocatedToAccountId() != null && ip.getAllocatedToAccountId() != Account.ACCOUNT_ID_SYSTEM) {
- VlanVO vlan = _vlanDao.findById(ip.getVlanId());
+ // Save usage event
+ if (ip.getAllocatedToAccountId() != null && ip.getAllocatedToAccountId() != Account.ACCOUNT_ID_SYSTEM) {
+ VlanVO vlan = _vlanDao.findById(ip.getVlanId());
- String guestType = vlan.getVlanType().toString();
- if (!isIpDedicated(ip)) {
- String eventType = ip.isPortable() ? EventTypes.EVENT_PORTABLE_IP_RELEASE : EventTypes.EVENT_NET_IP_RELEASE;
+ String guestType = vlan.getVlanType().toString();
+ if (!isIpDedicated(ip)) {
+ String eventType = ip.isPortable() ? EventTypes.EVENT_PORTABLE_IP_RELEASE : EventTypes.EVENT_NET_IP_RELEASE;
UsageEventUtils.publishUsageEvent(eventType, ip.getAllocatedToAccountId(), ip.getDataCenterId(), addrId, ip.getAddress().addr(), ip.isSourceNat(),
guestType, ip.getSystem(), ip.getClass().getName(), ip.getUuid());
- }
- }
+ }
+ }
return _ipAddressDao.markAsUnavailable(addrId);
}
@@ -1880,80 +1955,79 @@ public void allocateDirectIp(final NicProfile nic, final DataCenter dc, final Vi
Transaction.execute(new TransactionCallbackWithExceptionNoReturn<InsufficientAddressCapacityException>() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) throws InsufficientAddressCapacityException {
- //This method allocates direct ip for the Shared network in Advance zones
- boolean ipv4 = false;
-
- if (network.getGateway() != null) {
- if (nic.getIPv4Address() == null) {
- ipv4 = true;
- PublicIp ip = null;
-
- //Get ip address from the placeholder and don't allocate a new one
- if (requestedIpv4 != null && vm.getType() == VirtualMachine.Type.DomainRouter) {
- Nic placeholderNic = _networkModel.getPlaceholderNicForRouter(network, null);
- if (placeholderNic != null) {
- IPAddressVO userIp = _ipAddressDao.findByIpAndSourceNetworkId(network.getId(), placeholderNic.getIPv4Address());
- ip = PublicIp.createFromAddrAndVlan(userIp, _vlanDao.findById(userIp.getVlanId()));
- s_logger.debug("Nic got an ip address " + placeholderNic.getIPv4Address() + " stored in placeholder nic for the network " + network);
- }
- }
+ //This method allocates direct ip for the Shared network in Advance zones
+ boolean ipv4 = false;
- if (ip == null) {
- ip = assignPublicIpAddress(dc.getId(), null, vm.getOwner(), VlanType.DirectAttached, network.getId(), requestedIpv4, false);
- }
+ if (network.getGateway() != null) {
+ if (nic.getIPv4Address() == null) {
+ ipv4 = true;
+ PublicIp ip = null;
+
+ //Get ip address from the placeholder and don't allocate a new one
+ if (requestedIpv4 != null && vm.getType() == VirtualMachine.Type.DomainRouter) {
+ Nic placeholderNic = _networkModel.getPlaceholderNicForRouter(network, null);
+ if (placeholderNic != null) {
+ IPAddressVO userIp = _ipAddressDao.findByIpAndSourceNetworkId(network.getId(), placeholderNic.getIPv4Address());
+ ip = PublicIp.createFromAddrAndVlan(userIp, _vlanDao.findById(userIp.getVlanId()));
+ s_logger.debug("Nic got an ip address " + placeholderNic.getIPv4Address() + " stored in placeholder nic for the network " + network);
+ }
+ }
- nic.setIPv4Address(ip.getAddress().toString());
- nic.setIPv4Gateway(ip.getGateway());
- nic.setIPv4Netmask(ip.getNetmask());
- nic.setIsolationUri(IsolationType.Vlan.toUri(ip.getVlanTag()));
- //nic.setBroadcastType(BroadcastDomainType.Vlan);
- //nic.setBroadcastUri(BroadcastDomainType.Vlan.toUri(ip.getVlanTag()));
- nic.setBroadcastType(network.getBroadcastDomainType());
+ if (ip == null) {
+ ip = assignPublicIpAddress(dc.getId(), null, vm.getOwner(), VlanType.DirectAttached, network.getId(), requestedIpv4, false);
+ }
+
+ nic.setIPv4Address(ip.getAddress().toString());
+ nic.setIPv4Gateway(ip.getGateway());
+ nic.setIPv4Netmask(ip.getNetmask());
+ nic.setIsolationUri(IsolationType.Vlan.toUri(ip.getVlanTag()));
+ nic.setBroadcastType(network.getBroadcastDomainType());
if (network.getBroadcastUri() != null)
- nic.setBroadcastUri(network.getBroadcastUri());
+ nic.setBroadcastUri(network.getBroadcastUri());
else
nic.setBroadcastUri(BroadcastDomainType.Vlan.toUri(ip.getVlanTag()));
- nic.setFormat(AddressFormat.Ip4);
- nic.setReservationId(String.valueOf(ip.getVlanTag()));
- nic.setMacAddress(ip.getMacAddress());
- }
- nic.setIPv4Dns1(dc.getDns1());
- nic.setIPv4Dns2(dc.getDns2());
- }
-
- //FIXME - get ipv6 address from the placeholder if it's stored there
- if (network.getIp6Gateway() != null) {
- if (nic.getIPv6Address() == null) {
- UserIpv6Address ip = _ipv6Mgr.assignDirectIp6Address(dc.getId(), vm.getOwner(), network.getId(), requestedIpv6);
- Vlan vlan = _vlanDao.findById(ip.getVlanId());
- nic.setIPv6Address(ip.getAddress().toString());
- nic.setIPv6Gateway(vlan.getIp6Gateway());
- nic.setIPv6Cidr(vlan.getIp6Cidr());
- if (ipv4) {
- nic.setFormat(AddressFormat.DualStack);
- } else {
- nic.setIsolationUri(IsolationType.Vlan.toUri(vlan.getVlanTag()));
- nic.setBroadcastType(BroadcastDomainType.Vlan);
- nic.setBroadcastUri(BroadcastDomainType.Vlan.toUri(vlan.getVlanTag()));
- nic.setFormat(AddressFormat.Ip6);
- nic.setReservationId(String.valueOf(vlan.getVlanTag()));
- nic.setMacAddress(ip.getMacAddress());
+ nic.setFormat(AddressFormat.Ip4);
+ nic.setReservationId(String.valueOf(ip.getVlanTag()));
+ if(nic.getMacAddress() == null) {
+ nic.setMacAddress(ip.getMacAddress());
+ }
+ }
+ nic.setIPv4Dns1(dc.getDns1());
+ nic.setIPv4Dns2(dc.getDns2());
+ }
+
+ //FIXME - get ipv6 address from the placeholder if it's stored there
+ if (network.getIp6Gateway() != null) {
+ if (nic.getIPv6Address() == null) {
+ UserIpv6Address ip = _ipv6Mgr.assignDirectIp6Address(dc.getId(), vm.getOwner(), network.getId(), requestedIpv6);
+ Vlan vlan = _vlanDao.findById(ip.getVlanId());
+ nic.setIPv6Address(ip.getAddress().toString());
+ nic.setIPv6Gateway(vlan.getIp6Gateway());
+ nic.setIPv6Cidr(vlan.getIp6Cidr());
+ if (ipv4) {
+ nic.setFormat(AddressFormat.DualStack);
+ } else {
+ nic.setIsolationUri(IsolationType.Vlan.toUri(vlan.getVlanTag()));
+ nic.setBroadcastType(BroadcastDomainType.Vlan);
+ nic.setBroadcastUri(BroadcastDomainType.Vlan.toUri(vlan.getVlanTag()));
+ nic.setFormat(AddressFormat.Ip6);
+ nic.setReservationId(String.valueOf(vlan.getVlanTag()));
+ if(nic.getMacAddress() == null) {
+ nic.setMacAddress(ip.getMacAddress());
+ }
+ }
+ }
+ nic.setIPv6Dns1(dc.getIp6Dns1());
+ nic.setIPv6Dns2(dc.getIp6Dns2());
}
- }
- nic.setIPv6Dns1(dc.getIp6Dns1());
- nic.setIPv6Dns2(dc.getIp6Dns2());
- }
}
});
}
-
-
-
@Override
@DB
public void allocateNicValues(final NicProfile nic, final DataCenter dc, final VirtualMachineProfile vm, final Network network, final String requestedIpv4,
- final String requestedIpv6) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException {
+ final String requestedIpv6) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException {
Transaction.execute(new TransactionCallbackWithExceptionNoReturn<InsufficientAddressCapacityException>() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) throws InsufficientAddressCapacityException {
@@ -1967,7 +2041,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) throws Insuff
//Get ip address from the placeholder and don't allocate a new one
if (requestedIpv4 != null && vm.getType() == VirtualMachine.Type.DomainRouter) {
- s_logger.debug("There won't be nic assignment for VR id " + vm.getId() +" in this network " + network);
+ s_logger.debug("There won't be nic assignment for VR id " + vm.getId() + " in this network " + network);
}
@@ -1978,7 +2052,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) throws Insuff
List<VlanVO> vlan = _vlanDao.listVlansByNetworkId(network.getId());
//TODO: get vlan tag for the ntwork
- if (vlan != null && ! vlan.isEmpty()) {
+ if (vlan != null && !vlan.isEmpty()) {
nic.setIsolationUri(IsolationType.Vlan.toUri(vlan.get(0).getVlanTag()));
}
@@ -1987,8 +2061,9 @@ public void doInTransactionWithoutResult(TransactionStatus status) throws Insuff
nic.setBroadcastUri(network.getBroadcastUri());
nic.setFormat(AddressFormat.Ip4);
-
- nic.setMacAddress(_networkModel.getNextAvailableMacAddressInNetwork(network.getId()));
+ if(nic.getMacAddress() == null) {
+ nic.setMacAddress(_networkModel.getNextAvailableMacAddressInNetwork(network.getId()));
+ }
}
nic.setIPv4Dns1(dc.getDns1());
nic.setIPv4Dns2(dc.getDns2());
diff --git a/server/src/com/cloud/network/NetworkModelImpl.java b/server/src/com/cloud/network/NetworkModelImpl.java
index fbed85179b3..2efec9a0999 100644
--- a/server/src/com/cloud/network/NetworkModelImpl.java
+++ b/server/src/com/cloud/network/NetworkModelImpl.java
@@ -62,6 +62,7 @@
import com.cloud.network.IpAddress.State;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.GuestType;
+import com.cloud.network.Network.IpAddresses;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.Networks.TrafficType;
@@ -2169,7 +2170,10 @@ public void checkIp6Parameters(String startIPv6, String endIPv6, String ip6Gatew
}
@Override
- public void checkRequestedIpAddresses(long networkId, String ip4, String ip6) throws InvalidParameterValueException {
+ public void checkRequestedIpAddresses(long networkId, IpAddresses ips) throws InvalidParameterValueException {
+ String ip4 = ips.getIp4Address();
+ String ip6 = ips.getIp6Address();
+ String mac = ips.getMacAddress();
if (ip4 != null) {
if (!NetUtils.isValidIp(ip4)) {
throw new InvalidParameterValueException("Invalid specified IPv4 address " + ip4);
@@ -2198,6 +2202,15 @@ public void checkRequestedIpAddresses(long networkId, String ip4, String ip6) th
throw new InvalidParameterValueException("Requested IPv6 is not in the predefined range!");
}
}
+ if (mac != null) {
+ if(!NetUtils.isValidMac(mac)) {
+ throw new InvalidParameterValueException("Invalid specified MAC address " + mac);
+ }
+ if (_nicDao.findByNetworkIdAndMacAddress(networkId, mac) != null) {
+ throw new InvalidParameterValueException("The requested Mac address is already taken! " + mac);
+ }
+
+ }
}
@Override
@@ -2377,4 +2390,10 @@ public String getConfigComponentName() {
public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey<?>[] {MACIdentifier};
}
+
+ @Override
+ public String getValidNetworkCidr(Network guestNetwork) {
+ String networkCidr = guestNetwork.getNetworkCidr();
+ return networkCidr == null ? guestNetwork.getCidr() : networkCidr;
+ }
}
diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java
index 26ad1db5796..966c0e4475b 100644
--- a/server/src/com/cloud/network/NetworkServiceImpl.java
+++ b/server/src/com/cloud/network/NetworkServiceImpl.java
@@ -42,6 +42,7 @@
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.command.admin.address.ReleasePodIpCmdByAdmin;
import org.apache.cloudstack.api.command.admin.network.CreateNetworkCmdByAdmin;
import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd;
import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd;
@@ -50,6 +51,7 @@
import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd;
import org.apache.cloudstack.api.command.user.vm.ListNicsCmd;
+import org.apache.cloudstack.api.response.AcquirePodIpCmdResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
@@ -1036,9 +1038,14 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac
String netmask = cmd.getNetmask();
String networkDomain = cmd.getNetworkDomain();
String vlanId = null;
+ boolean bypassVlanOverlapCheck = false;
if (cmd instanceof CreateNetworkCmdByAdmin) {
vlanId = ((CreateNetworkCmdByAdmin)cmd).getVlan();
}
+ if (cmd instanceof CreateNetworkCmdByAdmin) {
+ bypassVlanOverlapCheck = ((CreateNetworkCmdByAdmin)cmd).getBypassVlanOverlapCheck();
+ }
+
String name = cmd.getNetworkName();
String displayText = cmd.getDisplayText();
Account caller = CallContext.current().getCallingAccount();
@@ -1257,8 +1264,8 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac
}
// Don't allow to specify vlan if the caller is not ROOT admin
- if (!_accountMgr.isRootAdmin(caller.getId()) && (ntwkOff.getSpecifyVlan() || vlanId != null)) {
- throw new InvalidParameterValueException("Only ROOT admin is allowed to specify vlanId");
+ if (!_accountMgr.isRootAdmin(caller.getId()) && (ntwkOff.getSpecifyVlan() || vlanId != null || bypassVlanOverlapCheck)) {
+ throw new InvalidParameterValueException("Only ROOT admin is allowed to specify vlanId or bypass vlan overlap check");
}
if (ipv4) {
@@ -1317,7 +1324,7 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac
throw ex;
}
- Network network = commitNetwork(networkOfferingId, gateway, startIP, endIP, netmask, networkDomain, vlanId, name, displayText, caller, physicalNetworkId, zoneId, domainId,
+ Network network = commitNetwork(networkOfferingId, gateway, startIP, endIP, netmask, networkDomain, vlanId, bypassVlanOverlapCheck, name, displayText, caller, physicalNetworkId, zoneId, domainId,
isDomainSpecific, subdomainAccess, vpcId, startIPv6, endIPv6, ip6Gateway, ip6Cidr, displayNetwork, aclId, isolatedPvlan, ntwkOff, pNtwk, aclType, owner, cidr,
createVlan);
@@ -1349,10 +1356,10 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac
}
private Network commitNetwork(final Long networkOfferingId, final String gateway, final String startIP, final String endIP, final String netmask, final String networkDomain,
- final String vlanId, final String name, final String displayText, final Account caller, final Long physicalNetworkId, final Long zoneId, final Long domainId,
- final boolean isDomainSpecific, final Boolean subdomainAccessFinal, final Long vpcId, final String startIPv6, final String endIPv6, final String ip6Gateway,
- final String ip6Cidr, final Boolean displayNetwork, final Long aclId, final String isolatedPvlan, final NetworkOfferingVO ntwkOff, final PhysicalNetwork pNtwk,
- final ACLType aclType, final Account ownerFinal, final String cidr, final boolean createVlan) throws InsufficientCapacityException, ResourceAllocationException {
+ final String vlanId, final Boolean bypassVlanOverlapCheck, final String name, final String displayText, final Account caller, final Long physicalNetworkId, final Long zoneId, final Long domainId,
+ final boolean isDomainSpecific, final Boolean subdomainAccessFinal, final Long vpcId, final String startIPv6, final String endIPv6, final String ip6Gateway,
+ final String ip6Cidr, final Boolean displayNetwork, final Long aclId, final String isolatedPvlan, final NetworkOfferingVO ntwkOff, final PhysicalNetwork pNtwk,
+ final ACLType aclType, final Account ownerFinal, final String cidr, final boolean createVlan) throws InsufficientCapacityException, ResourceAllocationException {
try {
Network network = Transaction.execute(new TransactionCallbackWithException<Network, Exception>() {
@Override
@@ -1406,14 +1413,14 @@ public Network doInTransaction(TransactionStatus status) throws InsufficientCapa
throw new InvalidParameterValueException("Internal Lb can be enabled on vpc networks only");
}
- network = _networkMgr.createGuestNetwork(networkOfferingId, name, displayText, gateway, cidr, vlanId, networkDomain, owner, sharedDomainId, pNtwk, zoneId,
+ network = _networkMgr.createGuestNetwork(networkOfferingId, name, displayText, gateway, cidr, vlanId, bypassVlanOverlapCheck, networkDomain, owner, sharedDomainId, pNtwk, zoneId,
aclType, subdomainAccess, vpcId, ip6Gateway, ip6Cidr, displayNetwork, isolatedPvlan);
}
if (_accountMgr.isRootAdmin(caller.getId()) && createVlan && network != null) {
// Create vlan ip range
_configMgr.createVlanAndPublicIpRange(pNtwk.getDataCenterId(), network.getId(), physicalNetworkId, false, null, startIP, endIP, gateway, netmask, vlanId,
- null, null, startIPv6, endIPv6, ip6Gateway, ip6Cidr);
+ bypassVlanOverlapCheck, null, null, startIPv6, endIPv6, ip6Gateway, ip6Cidr);
}
return network;
}
@@ -2119,7 +2126,7 @@ public Network updateGuestNetwork(final long networkId, String name, String disp
networkOfferingChanged = true;
//Setting the new network's isReduntant to the new network offering's RedundantRouter.
- network.setIsReduntant(_networkOfferingDao.findById(networkOfferingId).getRedundantRouter());
+ network.setRedundant(_networkOfferingDao.findById(networkOfferingId).getRedundantRouter());
}
}
@@ -4077,7 +4084,7 @@ public Network doInTransaction(TransactionStatus status) throws ResourceAllocati
Network privateNetwork = _networksDao.getPrivateNetwork(uriString, cidr, networkOwnerId, pNtwk.getDataCenterId(), networkOfferingId);
if (privateNetwork == null) {
//create Guest network
- privateNetwork = _networkMgr.createGuestNetwork(ntwkOffFinal.getId(), networkName, displayText, gateway, cidr, uriString, null, owner, null, pNtwk,
+ privateNetwork = _networkMgr.createGuestNetwork(ntwkOffFinal.getId(), networkName, displayText, gateway, cidr, uriString, false, null, owner, null, pNtwk,
pNtwk.getDataCenterId(), ACLType.Account, null, vpcId, null, null, true, null);
if (privateNetwork != null) {
s_logger.debug("Successfully created guest network " + privateNetwork);
@@ -4210,4 +4217,27 @@ public IpAddress updateIP(Long id, String customId, Boolean displayIp) {
return _ipAddressDao.findById(id);
}
+ @Override
+ public AcquirePodIpCmdResponse allocatePodIp(Account ipOwner, String zoneId, String podId) throws ResourceAllocationException {
+
+ Account caller = CallContext.current().getCallingAccount();
+ long callerUserId = CallContext.current().getCallingUserId();
+ DataCenter zone = _entityMgr.findByUuid(DataCenter.class, zoneId);
+
+ if (zone == null)
+ throw new InvalidParameterValueException("Invalid zone Id ");
+ if (_accountMgr.checkAccessAndSpecifyAuthority(caller, zone.getId()) != zone.getId())
+ throw new InvalidParameterValueException("Caller does not have permission for this Zone" + "(" + zoneId + ")");
+ if (s_logger.isDebugEnabled())
+ s_logger.debug("Associate IP address called by the user " + callerUserId + " account " + ipOwner.getId());
+ return _ipAddrMgr.allocatePodIp(zoneId, podId);
+
+ }
+
+ @Override
+ public boolean releasePodIp(ReleasePodIpCmdByAdmin ip) throws CloudRuntimeException {
+ _ipAddrMgr.releasePodIp(ip.getId());
+ return true;
+ }
+
}
diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java
index 4cc44c40478..01bded0eff2 100644
--- a/server/src/com/cloud/network/element/VirtualRouterElement.java
+++ b/server/src/com/cloud/network/element/VirtualRouterElement.java
@@ -23,7 +23,9 @@
import java.util.Set;
import javax.inject.Inject;
-
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import com.cloud.network.router.NetworkHelper;
import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;
import org.cloud.network.router.deployment.RouterDeploymentDefinition;
@@ -78,7 +80,6 @@
import com.cloud.network.dao.OvsProviderDao;
import com.cloud.network.dao.VirtualRouterProviderDao;
import com.cloud.network.lb.LoadBalancingRule;
-import com.cloud.network.lb.LoadBalancingRule.LbStickinessPolicy;
import com.cloud.network.lb.LoadBalancingRulesManager;
import com.cloud.network.router.VirtualRouter;
import com.cloud.network.router.VirtualRouter.Role;
@@ -95,13 +96,11 @@
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
-import com.cloud.utils.Pair;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.db.QueryBuilder;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.exception.CloudRuntimeException;
-import com.cloud.utils.net.NetUtils;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
@@ -171,6 +170,10 @@
@Inject
protected RouterDeploymentDefinitionBuilder routerDeploymentDefinitionBuilder;
+ @Autowired
+ @Qualifier("networkHelper")
+ protected NetworkHelper _networkHelper;
+
protected boolean canHandle(final Network network, final Service service) {
final Long physicalNetworkId = _networkMdl.getPhysicalNetworkId(network);
if (physicalNetworkId == null) {
@@ -302,104 +305,6 @@ public boolean applyFWRules(final Network network, final List<? extends Firewall
return result;
}
- /*
- * This function detects numbers like 12 ,32h ,42m .. etc,. 1) plain number
- * like 12 2) time or tablesize like 12h, 34m, 45k, 54m , here last
- * character is non-digit but from known characters .
- */
- private static boolean containsOnlyNumbers(final String str, final String endChar) {
- if (str == null) {
- return false;
- }
-
- String number = str;
- if (endChar != null) {
- boolean matchedEndChar = false;
- if (str.length() < 2) {
- return false; // at least one numeric and one char. example:
- }
- // 3h
- final char strEnd = str.toCharArray()[str.length() - 1];
- for (final char c : endChar.toCharArray()) {
- if (strEnd == c) {
- number = str.substring(0, str.length() - 1);
- matchedEndChar = true;
- break;
- }
- }
- if (!matchedEndChar) {
- return false;
- }
- }
- try {
- Integer.parseInt(number);
- } catch (final NumberFormatException e) {
- return false;
- }
- return true;
- }
-
- public static boolean validateHAProxyLBRule(final LoadBalancingRule rule) {
- final String timeEndChar = "dhms";
-
- if (rule.getSourcePortStart() == NetUtils.HAPROXY_STATS_PORT) {
- s_logger.debug("Can't create LB on port 8081, haproxy is listening for LB stats on this port");
- return false;
- }
-
- for (final LbStickinessPolicy stickinessPolicy : rule.getStickinessPolicies()) {
- final List<Pair<String, String>> paramsList = stickinessPolicy.getParams();
-
- if (StickinessMethodType.LBCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName())) {
-
- } else if (StickinessMethodType.SourceBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName())) {
- String tablesize = "200k"; // optional
- String expire = "30m"; // optional
-
- /* overwrite default values with the stick parameters */
- for (final Pair<String, String> paramKV : paramsList) {
- final String key = paramKV.first();
- final String value = paramKV.second();
- if ("tablesize".equalsIgnoreCase(key)) {
- tablesize = value;
- }
- if ("expire".equalsIgnoreCase(key)) {
- expire = value;
- }
- }
- if (expire != null && !containsOnlyNumbers(expire, timeEndChar)) {
- throw new InvalidParameterValueException("Failed LB in validation rule id: " + rule.getId() + " Cause: expire is not in timeformat: " + expire);
- }
- if (tablesize != null && !containsOnlyNumbers(tablesize, "kmg")) {
- throw new InvalidParameterValueException("Failed LB in validation rule id: " + rule.getId() + " Cause: tablesize is not in size format: " + tablesize);
-
- }
- } else if (StickinessMethodType.AppCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName())) {
- String length = null; // optional
- String holdTime = null; // optional
-
- for (final Pair<String, String> paramKV : paramsList) {
- final String key = paramKV.first();
- final String value = paramKV.second();
- if ("length".equalsIgnoreCase(key)) {
- length = value;
- }
- if ("holdtime".equalsIgnoreCase(key)) {
- holdTime = value;
- }
- }
-
- if (length != null && !containsOnlyNumbers(length, null)) {
- throw new InvalidParameterValueException("Failed LB in validation rule id: " + rule.getId() + " Cause: length is not a number: " + length);
- }
- if (holdTime != null && !containsOnlyNumbers(holdTime, timeEndChar) && !containsOnlyNumbers(holdTime, null)) {
- throw new InvalidParameterValueException("Failed LB in validation rule id: " + rule.getId() + " Cause: holdtime is not in timeformat: " + holdTime);
- }
- }
- }
- return true;
- }
-
@Override
public boolean validateLBRule(final Network network, final LoadBalancingRule rule) {
final List<LoadBalancingRule> rules = new ArrayList<LoadBalancingRule>();
@@ -409,7 +314,7 @@ public boolean validateLBRule(final Network network, final LoadBalancingRule rul
if (routers == null || routers.isEmpty()) {
return true;
}
- return validateHAProxyLBRule(rule);
+ return _networkHelper.validateHAProxyLBRule(rule);
}
return true;
}
diff --git a/server/src/com/cloud/network/guru/DirectNetworkGuru.java b/server/src/com/cloud/network/guru/DirectNetworkGuru.java
index 09afd6b7aa2..c92bb45dfef 100644
--- a/server/src/com/cloud/network/guru/DirectNetworkGuru.java
+++ b/server/src/com/cloud/network/guru/DirectNetworkGuru.java
@@ -35,6 +35,8 @@
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InsufficientVirtualNetworkCapacityException;
import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.network.dao.PhysicalNetworkDao;
+import com.cloud.network.dao.PhysicalNetworkVO;
import com.cloud.network.IpAddressManager;
import com.cloud.network.Ipv6AddressManager;
import com.cloud.network.Network;
@@ -46,6 +48,8 @@
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.Mode;
import com.cloud.network.Networks.TrafficType;
+import com.cloud.network.PhysicalNetwork;
+import com.cloud.network.PhysicalNetwork.IsolationMethod;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.dao.NetworkVO;
@@ -99,8 +103,11 @@
IpAddressManager _ipAddrMgr;
@Inject
NetworkOfferingServiceMapDao _ntwkOfferingSrvcDao;
+ @Inject
+ PhysicalNetworkDao _physicalNetworkDao;
private static final TrafficType[] TrafficTypes = {TrafficType.Guest};
+ protected IsolationMethod[] _isolationMethods;
@Override
public boolean isMyTrafficType(TrafficType type) {
@@ -112,14 +119,23 @@ public boolean isMyTrafficType(TrafficType type) {
return false;
}
+ protected boolean isMyIsolationMethod(PhysicalNetwork physicalNetwork) {
+ for (IsolationMethod m : _isolationMethods) {
+ if (physicalNetwork.getIsolationMethods().contains(m.toString())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
public TrafficType[] getSupportedTrafficType() {
return TrafficTypes;
}
- protected boolean canHandle(NetworkOffering offering, DataCenter dc) {
+ protected boolean canHandle(NetworkOffering offering, DataCenter dc, PhysicalNetwork physnet) {
// this guru handles only Guest networks in Advance zone with source nat service disabled
- if (dc.getNetworkType() == NetworkType.Advanced && isMyTrafficType(offering.getTrafficType()) && offering.getGuestType() == GuestType.Shared
+ if (dc.getNetworkType() == NetworkType.Advanced && isMyTrafficType(offering.getTrafficType()) && isMyIsolationMethod(physnet) && offering.getGuestType() == GuestType.Shared
&& !_ntwkOfferingSrvcDao.isProviderForNetworkOffering(offering.getId(), Network.Provider.NuageVsp)
&& !_ntwkOfferingSrvcDao.isProviderForNetworkOffering(offering.getId(), Network.Provider.NiciraNvp)) {
return true;
@@ -132,8 +148,9 @@ protected boolean canHandle(NetworkOffering offering, DataCenter dc) {
@Override
public Network design(NetworkOffering offering, DeploymentPlan plan, Network userSpecified, Account owner) {
DataCenter dc = _dcDao.findById(plan.getDataCenterId());
+ PhysicalNetworkVO physnet = _physicalNetworkDao.findById(plan.getPhysicalNetworkId());
- if (!canHandle(offering, dc)) {
+ if (!canHandle(offering, dc, physnet)) {
return null;
}
@@ -190,6 +207,7 @@ public Network design(NetworkOffering offering, DeploymentPlan plan, Network use
protected DirectNetworkGuru() {
super();
+ _isolationMethods = new IsolationMethod[] { new IsolationMethod("VLAN") };
}
@Override
diff --git a/server/src/com/cloud/network/guru/DirectPodBasedNetworkGuru.java b/server/src/com/cloud/network/guru/DirectPodBasedNetworkGuru.java
index 6301ca50e1b..f9657be4775 100644
--- a/server/src/com/cloud/network/guru/DirectPodBasedNetworkGuru.java
+++ b/server/src/com/cloud/network/guru/DirectPodBasedNetworkGuru.java
@@ -47,6 +47,7 @@
import com.cloud.network.addr.PublicIp;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.IPAddressVO;
+import com.cloud.network.PhysicalNetwork;
import com.cloud.offering.NetworkOffering;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.utils.db.DB;
@@ -83,8 +84,8 @@
IpAddressManager _ipAddrMgr;
@Override
- protected boolean canHandle(NetworkOffering offering, DataCenter dc) {
- // this guru handles system Direct pod based network
+ protected boolean canHandle(NetworkOffering offering, DataCenter dc, PhysicalNetwork physnet) {
+ // this guru handles system Direct pod based network in Basic zones only (no isolation type specified)
if (dc.getNetworkType() == NetworkType.Basic && isMyTrafficType(offering.getTrafficType())) {
return true;
} else {
diff --git a/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java b/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java
index a5838ecb392..a6bc4f0d97e 100644
--- a/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java
+++ b/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java
@@ -16,13 +16,6 @@
// under the License.
package com.cloud.network.guru;
-import java.util.List;
-
-import javax.inject.Inject;
-
-import org.apache.cloudstack.context.CallContext;
-import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
-import org.apache.log4j.Logger;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenter.NetworkType;
@@ -63,6 +56,12 @@
import com.cloud.vm.NicVO;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachineProfile;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
+import org.apache.log4j.Logger;
+
+import javax.inject.Inject;
+import java.util.List;
public class ExternalGuestNetworkGuru extends GuestNetworkGuru {
private static final Logger s_logger = Logger.getLogger(ExternalGuestNetworkGuru.class);
@@ -85,7 +84,7 @@
public ExternalGuestNetworkGuru() {
super();
- _isolationMethods = new IsolationMethod[] {IsolationMethod.GRE, IsolationMethod.L3, IsolationMethod.VLAN};
+ _isolationMethods = new IsolationMethod[] {new IsolationMethod("GRE"), new IsolationMethod("L3"), new IsolationMethod("VLAN")};
}
@Override
diff --git a/server/src/com/cloud/network/guru/GuestNetworkGuru.java b/server/src/com/cloud/network/guru/GuestNetworkGuru.java
index f6aeeab197f..74d774065c1 100644
--- a/server/src/com/cloud/network/guru/GuestNetworkGuru.java
+++ b/server/src/com/cloud/network/guru/GuestNetworkGuru.java
@@ -376,7 +376,7 @@ public NicProfile allocate(final Network network, NicProfile nic, final VirtualM
}
nic.setIPv4Address(guestIp);
- nic.setIPv4Netmask(NetUtils.cidr2Netmask(network.getCidr()));
+ nic.setIPv4Netmask(NetUtils.cidr2Netmask(_networkModel.getValidNetworkCidr(network)));
nic.setIPv4Dns1(dc.getDns1());
nic.setIPv4Dns2(dc.getDns2());
diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java
index 5e19ad7b1b9..9b7cf9b4230 100644
--- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java
+++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java
@@ -875,13 +875,10 @@ public void updateLBHealthChecks(Scheme scheme) throws ResourceUnavailableExcept
for (LoadBalancerVO lb : rules) {
List<LbDestination> dstList = getExistingDestinations(lb.getId());
List<LbHealthCheckPolicy> hcPolicyList = getHealthCheckPolicies(lb.getId());
- // adding to lbrules list only if the LB rule
- // hashealtChecks
- if (hcPolicyList != null && hcPolicyList.size() > 0) {
- Ip sourceIp = getSourceIp(lb);
- LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList, null, hcPolicyList, sourceIp, null, lb.getLbProtocol());
- lbrules.add(loadBalancing);
- }
+ // Now retrive the status of services from NS even there are no policies. because there is default monitor
+ Ip sourceIp = getSourceIp(lb);
+ LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList, null, hcPolicyList, sourceIp, null, lb.getLbProtocol());
+ lbrules.add(loadBalancing);
}
if (lbrules.size() > 0) {
isHandled = false;
@@ -2124,10 +2121,11 @@ public LoadBalancer updateLoadBalancerRule(UpdateLoadBalancerRuleCmd cmd) {
throw new InvalidParameterValueException("Modifications in lb rule " + lbRuleId + " are not supported.");
}
+ LoadBalancerVO tmplbVo = _lbDao.findById(lbRuleId);
boolean success = _lbDao.update(lbRuleId, lb);
// If algorithm is changed, have to reapply the lb config
- if (algorithm != null) {
+ if ((algorithm != null) && (tmplbVo.getAlgorithm().compareTo(algorithm) != 0)){
try {
lb.setState(FirewallRule.State.Add);
_lbDao.persist(lb);
diff --git a/server/src/com/cloud/network/router/CommandSetupHelper.java b/server/src/com/cloud/network/router/CommandSetupHelper.java
index d00c9a8861b..cadaf4fcdf8 100644
--- a/server/src/com/cloud/network/router/CommandSetupHelper.java
+++ b/server/src/com/cloud/network/router/CommandSetupHelper.java
@@ -601,7 +601,9 @@ public void createVmDataCommandForVMs(final DomainRouterVO router, final Command
final NicVO nic = _nicDao.findByNtwkIdAndInstanceId(guestNetworkId, vm.getId());
if (nic != null) {
s_logger.debug("Creating user data entry for vm " + vm + " on domR " + router);
- createVmDataCommand(router, vm, nic, null, cmds);
+
+ _userVmDao.loadDetails(vm);
+ createVmDataCommand(router, vm, nic, vm.getDetail("SSH.PublicKey"), cmds);
}
}
}
diff --git a/server/src/com/cloud/network/router/NetworkHelper.java b/server/src/com/cloud/network/router/NetworkHelper.java
index 380cecdafcf..04604e19d78 100644
--- a/server/src/com/cloud/network/router/NetworkHelper.java
+++ b/server/src/com/cloud/network/router/NetworkHelper.java
@@ -21,6 +21,7 @@
import java.util.Map;
import org.cloud.network.router.deployment.RouterDeploymentDefinition;
+import com.cloud.network.lb.LoadBalancingRule;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.manager.Commands;
@@ -89,4 +90,6 @@ public abstract void reallocateRouterNetworks(RouterDeploymentDefinition routerD
public abstract LinkedHashMap<Network, List<? extends NicProfile>> configureGuestNic(RouterDeploymentDefinition routerDeploymentDefinition)
throws ConcurrentOperationException, InsufficientAddressCapacityException;
-}
\ No newline at end of file
+
+ public boolean validateHAProxyLBRule(final LoadBalancingRule rule);
+}
diff --git a/server/src/com/cloud/network/router/NetworkHelperImpl.java b/server/src/com/cloud/network/router/NetworkHelperImpl.java
index 12ef0f9995e..398a7e9bc1b 100644
--- a/server/src/com/cloud/network/router/NetworkHelperImpl.java
+++ b/server/src/com/cloud/network/router/NetworkHelperImpl.java
@@ -27,6 +27,12 @@
import javax.annotation.PostConstruct;
import javax.ejb.Local;
import javax.inject.Inject;
+import com.cloud.configuration.Config;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.network.lb.LoadBalancingRule;
+import com.cloud.network.rules.LbStickinessMethod;
+import com.cloud.utils.Pair;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
@@ -147,6 +153,8 @@
protected VirtualMachineManager _itMgr;
@Inject
protected IpAddressManager _ipAddrMgr;
+ @Inject
+ ConfigurationDao _configDao;
protected final Map<HypervisorType, ConfigKey<String>> hypervisorsMap = new HashMap<>();
@@ -743,7 +751,7 @@ protected HypervisorType getClusterToStartDomainRouterForOvm(final long podId) {
gatewayNic.setBroadcastType(guestNetwork.getBroadcastDomainType());
gatewayNic.setIsolationUri(guestNetwork.getBroadcastUri());
gatewayNic.setMode(guestNetwork.getMode());
- final String gatewayCidr = guestNetwork.getCidr();
+ final String gatewayCidr = _networkModel.getValidNetworkCidr(guestNetwork);
gatewayNic.setIPv4Netmask(NetUtils.getCidrNetmask(gatewayCidr));
} else {
gatewayNic.setDefaultNic(true);
@@ -771,4 +779,103 @@ public static void setSystemAccount(final Account systemAccount) {
public static void setVMInstanceName(final String vmInstanceName) {
s_vmInstanceName = vmInstanceName;
}
+ public boolean validateHAProxyLBRule(final LoadBalancingRule rule) {
+ final String timeEndChar = "dhms";
+ int haproxy_stats_port = Integer.parseInt(_configDao.getValue(Config.NetworkLBHaproxyStatsPort.key()));
+ if (rule.getSourcePortStart() == haproxy_stats_port) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Can't create LB on port "+ haproxy_stats_port +", haproxy is listening for LB stats on this port");
+ }
+ return false;
+ }
+
+ for (final LoadBalancingRule.LbStickinessPolicy stickinessPolicy : rule.getStickinessPolicies()) {
+ final List<Pair<String, String>> paramsList = stickinessPolicy.getParams();
+
+ if (LbStickinessMethod.StickinessMethodType.LBCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName())) {
+
+ } else if (LbStickinessMethod.StickinessMethodType.SourceBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName())) {
+ String tablesize = "200k"; // optional
+ String expire = "30m"; // optional
+
+ /* overwrite default values with the stick parameters */
+ for (final Pair<String, String> paramKV : paramsList) {
+ final String key = paramKV.first();
+ final String value = paramKV.second();
+ if ("tablesize".equalsIgnoreCase(key)) {
+ tablesize = value;
+ }
+ if ("expire".equalsIgnoreCase(key)) {
+ expire = value;
+ }
+ }
+ if (expire != null && !containsOnlyNumbers(expire, timeEndChar)) {
+ throw new InvalidParameterValueException("Failed LB in validation rule id: " + rule.getId() + " Cause: expire is not in timeformat: " + expire);
+ }
+ if (tablesize != null && !containsOnlyNumbers(tablesize, "kmg")) {
+ throw new InvalidParameterValueException("Failed LB in validation rule id: " + rule.getId() + " Cause: tablesize is not in size format: " + tablesize);
+
+ }
+ } else if (LbStickinessMethod.StickinessMethodType.AppCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName())) {
+ String length = null; // optional
+ String holdTime = null; // optional
+
+ for (final Pair<String, String> paramKV : paramsList) {
+ final String key = paramKV.first();
+ final String value = paramKV.second();
+ if ("length".equalsIgnoreCase(key)) {
+ length = value;
+ }
+ if ("holdtime".equalsIgnoreCase(key)) {
+ holdTime = value;
+ }
+ }
+
+ if (length != null && !containsOnlyNumbers(length, null)) {
+ throw new InvalidParameterValueException("Failed LB in validation rule id: " + rule.getId() + " Cause: length is not a number: " + length);
+ }
+ if (holdTime != null && !containsOnlyNumbers(holdTime, timeEndChar) && !containsOnlyNumbers(holdTime, null)) {
+ throw new InvalidParameterValueException("Failed LB in validation rule id: " + rule.getId() + " Cause: holdtime is not in timeformat: " + holdTime);
+ }
+ }
+ }
+ return true;
+ }
+
+ /*
+ * This function detects numbers like 12 ,32h ,42m .. etc,. 1) plain number
+ * like 12 2) time or tablesize like 12h, 34m, 45k, 54m , here last
+ * character is non-digit but from known characters .
+ */
+ private static boolean containsOnlyNumbers(final String str, final String endChar) {
+ if (str == null) {
+ return false;
+ }
+
+ String number = str;
+ if (endChar != null) {
+ boolean matchedEndChar = false;
+ if (str.length() < 2) {
+ return false; // at least one numeric and one char. example:
+ }
+ // 3h
+ final char strEnd = str.toCharArray()[str.length() - 1];
+ for (final char c : endChar.toCharArray()) {
+ if (strEnd == c) {
+ number = str.substring(0, str.length() - 1);
+ matchedEndChar = true;
+ break;
+ }
+ }
+ if (!matchedEndChar) {
+ return false;
+ }
+ }
+ try {
+ Integer.parseInt(number);
+ } catch (final NumberFormatException e) {
+ return false;
+ }
+ return true;
+ }
}
diff --git a/server/src/com/cloud/network/router/NicProfileHelperImpl.java b/server/src/com/cloud/network/router/NicProfileHelperImpl.java
index 7575aad1b05..92a5915c4d5 100644
--- a/server/src/com/cloud/network/router/NicProfileHelperImpl.java
+++ b/server/src/com/cloud/network/router/NicProfileHelperImpl.java
@@ -127,7 +127,7 @@ public NicProfile createGuestNicProfileForVpcRouter(final RouterDeploymentDefini
guestNic.setBroadcastType(guestNetwork.getBroadcastDomainType());
guestNic.setIsolationUri(guestNetwork.getBroadcastUri());
guestNic.setMode(guestNetwork.getMode());
- final String gatewayCidr = guestNetwork.getCidr();
+ final String gatewayCidr = _networkModel.getValidNetworkCidr(guestNetwork);
guestNic.setIPv4Netmask(NetUtils.getCidrNetmask(gatewayCidr));
return guestNic;
diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
index 43669d191eb..e0b08d1a70f 100644
--- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
+++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
@@ -1535,7 +1535,7 @@ protected StringBuilder createGuestBootLoadArgs(final NicProfile guestNic, final
}
}
} else if (dc.getNetworkType() == NetworkType.Advanced) {
- final String cidr = guestNetwork.getCidr();
+ final String cidr = _networkModel.getValidNetworkCidr(guestNetwork);
if (cidr != null) {
cidrSize = NetUtils.getCidrSize(NetUtils.getCidrNetmask(cidr));
dhcpRange = NetUtils.getDhcpRange(cidr);
diff --git a/server/src/com/cloud/network/router/VpcNetworkHelperImpl.java b/server/src/com/cloud/network/router/VpcNetworkHelperImpl.java
index 8b1d9fe9852..b4cf809726d 100644
--- a/server/src/com/cloud/network/router/VpcNetworkHelperImpl.java
+++ b/server/src/com/cloud/network/router/VpcNetworkHelperImpl.java
@@ -21,6 +21,8 @@
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.TreeSet;
import javax.annotation.PostConstruct;
@@ -83,7 +85,10 @@ public void reallocateRouterNetworks(final RouterDeploymentDefinition vpcRouterD
throws ConcurrentOperationException, InsufficientCapacityException {
final TreeSet<String> publicVlans = new TreeSet<String>();
- publicVlans.add(vpcRouterDeploymentDefinition.getSourceNatIP().getVlanTag());
+ if (vpcRouterDeploymentDefinition.isPublicNetwork()) {
+ publicVlans.add(vpcRouterDeploymentDefinition.getSourceNatIP()
+ .getVlanTag());
+ }
//1) allocate nic for control and source nat public ip
final LinkedHashMap<Network, List<? extends NicProfile>> networks = configureDefaultNics(vpcRouterDeploymentDefinition);
@@ -115,43 +120,51 @@ public void reallocateRouterNetworks(final RouterDeploymentDefinition vpcRouterD
final List<IPAddressVO> ips = _ipAddressDao.listByAssociatedVpc(vpcId, false);
final List<NicProfile> publicNics = new ArrayList<NicProfile>();
Network publicNetwork = null;
+ final Map<Network.Service, Set<Network.Provider>> vpcOffSvcProvidersMap = vpcMgr.getVpcOffSvcProvidersMap(vpcRouterDeploymentDefinition.getVpc().getVpcOfferingId());
+
+ boolean vpcIsStaticNatProvider = vpcOffSvcProvidersMap.get(Network.Service.StaticNat) != null &&
+ vpcOffSvcProvidersMap.get(Network.Service.StaticNat).contains(Network.Provider.VPCVirtualRouter);
+
+ final ServiceOfferingVO routerOffering = _serviceOfferingDao.findById(vpcRouterDeploymentDefinition.getServiceOfferingId());
+
for (final IPAddressVO ip : ips) {
- final PublicIp publicIp = PublicIp.createFromAddrAndVlan(ip, _vlanDao.findById(ip.getVlanId()));
- if ((ip.getState() == IpAddress.State.Allocated || ip.getState() == IpAddress.State.Allocating) && vpcMgr.isIpAllocatedToVpc(ip) &&
- !publicVlans.contains(publicIp.getVlanTag())) {
- s_logger.debug("Allocating nic for router in vlan " + publicIp.getVlanTag());
- final NicProfile publicNic = new NicProfile();
- publicNic.setDefaultNic(false);
- publicNic.setIPv4Address(publicIp.getAddress().addr());
- publicNic.setIPv4Gateway(publicIp.getGateway());
- publicNic.setIPv4Netmask(publicIp.getNetmask());
- publicNic.setMacAddress(publicIp.getMacAddress());
- publicNic.setBroadcastType(BroadcastDomainType.Vlan);
- publicNic.setBroadcastUri(BroadcastDomainType.Vlan.toUri(publicIp.getVlanTag()));
- publicNic.setIsolationUri(IsolationType.Vlan.toUri(publicIp.getVlanTag()));
- final NetworkOffering publicOffering = _networkModel.getSystemAccountNetworkOfferings(NetworkOffering.SystemPublicNetwork).get(0);
- if (publicNetwork == null) {
- final List<? extends Network> publicNetworks = _networkMgr.setupNetwork(s_systemAccount, publicOffering, vpcRouterDeploymentDefinition.getPlan(), null, null, false);
- publicNetwork = publicNetworks.get(0);
+ if (vpcIsStaticNatProvider || !ip.isOneToOneNat()) {
+ final PublicIp publicIp = PublicIp.createFromAddrAndVlan(ip, _vlanDao.findById(ip.getVlanId()));
+ if ((ip.getState() == IpAddress.State.Allocated || ip.getState() == IpAddress.State.Allocating)
+ && vpcMgr.isIpAllocatedToVpc(ip)
+ && !publicVlans.contains(publicIp.getVlanTag())) {
+ s_logger.debug("Allocating nic for router in vlan " + publicIp.getVlanTag());
+ final NicProfile publicNic = new NicProfile();
+ publicNic.setDefaultNic(false);
+ publicNic.setIPv4Address(publicIp.getAddress()
+ .addr());
+ publicNic.setIPv4Gateway(publicIp.getGateway());
+ publicNic.setIPv4Netmask(publicIp.getNetmask());
+ publicNic.setMacAddress(publicIp.getMacAddress());
+ publicNic.setBroadcastType(BroadcastDomainType.Vlan);
+ publicNic.setBroadcastUri(BroadcastDomainType.Vlan.toUri(publicIp.getVlanTag()));
+ publicNic.setIsolationUri(IsolationType.Vlan.toUri(publicIp.getVlanTag()));
+ final NetworkOffering publicOffering = _networkModel.getSystemAccountNetworkOfferings(NetworkOffering.SystemPublicNetwork)
+ .get(0);
+ if (publicNetwork == null) {
+ final List<? extends Network> publicNetworks = _networkMgr.setupNetwork(s_systemAccount, publicOffering, vpcRouterDeploymentDefinition.getPlan(), null, null, false);
+ publicNetwork = publicNetworks.get(0);
+ }
+ publicNics.add(publicNic);
+ publicVlans.add(publicIp.getVlanTag());
}
- publicNics.add(publicNic);
- publicVlans.add(publicIp.getVlanTag());
}
- }
- if (publicNetwork != null) {
- if (networks.get(publicNetwork) != null) {
- @SuppressWarnings("unchecked")
- final
- List<NicProfile> publicNicProfiles = (List<NicProfile>)networks.get(publicNetwork);
- publicNicProfiles.addAll(publicNics);
- networks.put(publicNetwork, publicNicProfiles);
- } else {
- networks.put(publicNetwork, publicNics);
+ if (publicNetwork != null) {
+ if (networks.get(publicNetwork) != null) {
+ @SuppressWarnings("unchecked") final List<NicProfile> publicNicProfiles = (List<NicProfile>)networks.get(publicNetwork);
+ publicNicProfiles.addAll(publicNics);
+ networks.put(publicNetwork, publicNicProfiles);
+ } else {
+ networks.put(publicNetwork, publicNics);
+ }
}
}
- final ServiceOfferingVO routerOffering = _serviceOfferingDao.findById(vpcRouterDeploymentDefinition.getServiceOfferingId());
-
_itMgr.allocate(router.getInstanceName(), template, routerOffering, networks, vpcRouterDeploymentDefinition.getPlan(), hType);
}
diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java
index 629e35f5ba3..37a9ad90d33 100644
--- a/server/src/com/cloud/network/rules/RulesManagerImpl.java
+++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java
@@ -1525,7 +1525,7 @@ protected void removePFRule(PortForwardingRuleVO rule) {
@Override
@ActionEvent(eventType = EventTypes.EVENT_NET_RULE_MODIFY, eventDescription = "updating forwarding rule", async = true)
- public PortForwardingRule updatePortForwardingRule(long id, Integer privatePort, Long virtualMachineId, Ip vmGuestIp, String customId, Boolean forDisplay) {
+ public PortForwardingRule updatePortForwardingRule(long id, Integer privatePort, Integer privateEndPort, Long virtualMachineId, Ip vmGuestIp, String customId, Boolean forDisplay) {
Account caller = CallContext.current().getCallingAccount();
PortForwardingRuleVO rule = _portForwardingDao.findById(id);
if (rule == null) {
@@ -1541,9 +1541,29 @@ public PortForwardingRule updatePortForwardingRule(long id, Integer privatePort,
rule.setDisplay(forDisplay);
}
- if (!rule.getSourcePortStart().equals(rule.getSourcePortEnd()) && privatePort != null) {
- throw new InvalidParameterValueException("Unable to update the private port of port forwarding rule as the rule has port range : " + rule.getSourcePortStart() + " to " + rule.getSourcePortEnd());
+ if (privatePort != null && !NetUtils.isValidPort(privatePort)) {
+ throw new InvalidParameterValueException("privatePort is an invalid value: " + privatePort);
}
+ if (privateEndPort != null && !NetUtils.isValidPort(privateEndPort)) {
+ throw new InvalidParameterValueException("PrivateEndPort has an invalid value: " + privateEndPort);
+ }
+
+ if (privatePort != null && privateEndPort != null && ((privateEndPort - privatePort) != (rule.getSourcePortEnd() - rule.getSourcePortStart())))
+ {
+ throw new InvalidParameterValueException("Unable to update the private port range of port forwarding rule as " +
+ "the provided port range is not consistent with the port range : " + rule.getSourcePortStart() + " to " + rule.getSourcePortEnd());
+ }
+
+ //in case of port range
+ if (!rule.getSourcePortStart().equals(rule.getSourcePortEnd())) {
+ if ((privatePort == null || privateEndPort == null) && !(privatePort == null && privateEndPort == null)) {
+ throw new InvalidParameterValueException("Unable to update the private port range of port forwarding rule as " +
+ "the provided port range is not consistent with the port range : " + rule.getSourcePortStart() + " to " + rule.getSourcePortEnd());
+ }
+ }
+
+
+
if (virtualMachineId == null && vmGuestIp != null) {
throw new InvalidParameterValueException("vmguestip should be set along with virtualmachineid");
}
@@ -1588,8 +1608,12 @@ public PortForwardingRule updatePortForwardingRule(long id, Integer privatePort,
rule.setState(State.Add);
if (privatePort != null) {
rule.setDestinationPortStart(privatePort.intValue());
- rule.setDestinationPortEnd(privatePort.intValue());
+ rule.setDestinationPortEnd((privateEndPort == null) ? privatePort.intValue() : privateEndPort.intValue());
+ } else if (privateEndPort != null) {
+ rule.setDestinationPortStart(privateEndPort.intValue());
+ rule.setDestinationPortEnd(privateEndPort);
}
+
if (virtualMachineId != null) {
rule.setVirtualMachineId(virtualMachineId);
rule.setDestinationIpAddress(dstIp);
diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java
index 706f4c4abff..5c35c15a1f8 100644
--- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java
+++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java
@@ -43,14 +43,12 @@
import org.apache.cloudstack.api.command.user.vpc.ListStaticRoutesCmd;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
-import org.apache.cloudstack.framework.config.ConfigDepot;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;
import com.cloud.configuration.Config;
-import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
@@ -88,8 +86,6 @@
import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkVO;
-import com.cloud.network.dao.PhysicalNetworkDao;
-import com.cloud.network.dao.Site2SiteVpnGatewayDao;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.element.StaticNatServiceProvider;
import com.cloud.network.element.VpcProvider;
@@ -108,7 +104,6 @@
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
import com.cloud.org.Grouping;
import com.cloud.projects.Project.ListProjectResourcesCriteria;
-import com.cloud.server.ConfigurationServer;
import com.cloud.server.ResourceTag.ResourceObjectType;
import com.cloud.tags.ResourceTagVO;
import com.cloud.tags.dao.ResourceTagDao;
@@ -140,7 +135,6 @@
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.ReservationContextImpl;
-import com.cloud.vm.dao.DomainRouterDao;
public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvisioningService, VpcService {
private static final Logger s_logger = Logger.getLogger(VpcManagerImpl.class);
@@ -162,8 +156,6 @@
@Inject
ConfigurationDao _configDao;
@Inject
- ConfigurationManager _configMgr;
- @Inject
AccountManager _accountMgr;
@Inject
NetworkDao _ntwkDao;
@@ -176,8 +168,6 @@
@Inject
IPAddressDao _ipAddressDao;
@Inject
- DomainRouterDao _routerDao;
- @Inject
VpcGatewayDao _vpcGatewayDao;
@Inject
PrivateIpDao _privateIpDao;
@@ -188,14 +178,10 @@
@Inject
VpcOfferingServiceMapDao _vpcOffServiceDao;
@Inject
- PhysicalNetworkDao _pNtwkDao;
- @Inject
ResourceTagDao _resourceTagDao;
@Inject
FirewallRulesDao _firewallDao;
@Inject
- Site2SiteVpnGatewayDao _vpnGatewayDao;
- @Inject
Site2SiteVpnManager _s2sVpnMgr;
@Inject
VlanDao _vlanDao = null;
@@ -206,17 +192,11 @@
@Inject
DataCenterDao _dcDao;
@Inject
- ConfigurationServer _configServer;
- @Inject
NetworkACLDao _networkAclDao;
@Inject
- NetworkACLItemDao _networkACLItemDao;
- @Inject
NetworkACLManager _networkAclMgr;
@Inject
IpAddressManager _ipAddrMgr;
- @Inject
- ConfigDepot _configDepot;
@Inject
private VpcPrivateGatewayTransactionCallable vpcTxCallable;
@@ -2266,14 +2246,9 @@ public IpAddress associateIPToVpc(final long ipId, final long vpcId) throws Reso
// check permissions
_accountMgr.checkAccess(caller, null, true, owner, vpc);
- boolean isSourceNat = false;
- if (getExistingSourceNatInVpc(owner.getId(), vpcId) == null) {
- isSourceNat = true;
- }
-
s_logger.debug("Associating ip " + ipToAssoc + " to vpc " + vpc);
- final boolean isSourceNatFinal = isSourceNat;
+ final boolean isSourceNatFinal = isSrcNatIpRequired(vpc.getVpcOfferingId()) && getExistingSourceNatInVpc(owner.getId(), vpcId) == null;
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(final TransactionStatus status) {
@@ -2359,7 +2334,7 @@ public Network createVpcGuestNetwork(final long ntwkOffId, final String name, fi
validateNtwkOffForNtwkInVpc(null, ntwkOffId, cidr, networkDomain, vpc, gateway, owner, aclId);
// 2) Create network
- final Network guestNetwork = _ntwkMgr.createGuestNetwork(ntwkOffId, name, displayText, gateway, cidr, vlanId, networkDomain, owner, domainId, pNtwk, zoneId, aclType,
+ final Network guestNetwork = _ntwkMgr.createGuestNetwork(ntwkOffId, name, displayText, gateway, cidr, vlanId, false, networkDomain, owner, domainId, pNtwk, zoneId, aclType,
subdomainAccess, vpcId, null, null, isDisplayNetworkEnabled, null);
if (guestNetwork != null) {
@@ -2449,4 +2424,10 @@ public boolean applyStaticRoute(final long routeId) throws ResourceUnavailableEx
final StaticRoute route = _staticRouteDao.findById(routeId);
return applyStaticRoutesForVpc(route.getVpcId());
}
+
+ @Override
+ public boolean isSrcNatIpRequired(long vpcOfferingId) {
+ final Map<Network.Service, Set<Network.Provider>> vpcOffSvcProvidersMap = getVpcOffSvcProvidersMap(vpcOfferingId);
+ return vpcOffSvcProvidersMap.get(Network.Service.SourceNat).contains(Network.Provider.VPCVirtualRouter);
+ }
}
diff --git a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java
index 67b1cc0faa5..491fb474109 100644
--- a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java
+++ b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java
@@ -381,8 +381,8 @@ public VpnUser addVpnUser(final long vpnOwnerId, final String username, final St
if (!username.matches("^[a-zA-Z0-9][a-zA-Z0-9@._-]{2,63}$")) {
throw new InvalidParameterValueException("Username has to be begin with an alphabet have 3-64 characters including alphabets, numbers and the set '@.-_'");
}
- if (!password.matches("^[a-zA-Z0-9][a-zA-Z0-9@#+=._-]{2,31}$")) {
- throw new InvalidParameterValueException("Password has to be 3-32 characters including alphabets, numbers and the set '@#+=.-_'");
+ if (!password.matches("^[a-zA-Z0-9][a-zA-Z0-9@+=._-]{2,31}$")) {
+ throw new InvalidParameterValueException("Password has to be 3-32 characters including alphabets, numbers and the set '@+=.-_'");
}
return Transaction.execute(new TransactionCallback<VpnUser>() {
diff --git a/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java b/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java
index e465bfb3529..ba8c1d1ade0 100644
--- a/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java
+++ b/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java
@@ -177,8 +177,8 @@ public Site2SiteCustomerGateway createCustomerGateway(CreateVpnCustomerGatewayCm
String name = cmd.getName();
String gatewayIp = cmd.getGatewayIp();
- if (!NetUtils.isValidIp(gatewayIp)) {
- throw new InvalidParameterValueException("The customer gateway ip " + gatewayIp + " is invalid!");
+ if (!NetUtils.isValidIp(gatewayIp) && !NetUtils.verifyDomainName(gatewayIp)) {
+ throw new InvalidParameterValueException("The customer gateway ip/Domain " + gatewayIp + " is invalid!");
}
if (name == null) {
name = "VPN-" + gatewayIp;
@@ -431,8 +431,8 @@ public Site2SiteCustomerGateway updateCustomerGateway(UpdateVpnCustomerGatewayCm
}
String name = cmd.getName();
String gatewayIp = cmd.getGatewayIp();
- if (!NetUtils.isValidIp(gatewayIp)) {
- throw new InvalidParameterValueException("The customer gateway ip " + gatewayIp + " is invalid!");
+ if (!NetUtils.isValidIp(gatewayIp) && !NetUtils.verifyDomainName(gatewayIp)) {
+ throw new InvalidParameterValueException("The customer gateway ip/Domain " + gatewayIp + " is invalid!");
}
if (name == null) {
name = "VPN-" + gatewayIp;
diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java
index af5344c8e62..9feb9b7f683 100755
--- a/server/src/com/cloud/resource/ResourceManagerImpl.java
+++ b/server/src/com/cloud/resource/ResourceManagerImpl.java
@@ -2272,7 +2272,8 @@ private boolean doCancelMaintenance(final long hostId) {
}
try {
- SSHCmdHelper.sshExecuteCmdOneShot(connection, "service cloudstack-agent restart");
+ SSHCmdHelper.SSHCmdResult result = SSHCmdHelper.sshExecuteCmdOneShot(connection, "service cloudstack-agent restart || systemctl restart cloudstack-agent");
+ s_logger.debug("cloudstack-agent restart result: " + result.toString());
} catch (final SshException e) {
return false;
}
@@ -2516,6 +2517,23 @@ public boolean maintenanceFailed(final long hostId) {
return sc.list();
}
+ @Override
+ public List<HostVO> listAllUpHosts(Type type, Long clusterId, Long podId, long dcId) {
+ final QueryBuilder<HostVO> sc = QueryBuilder.create(HostVO.class);
+ if (type != null) {
+ sc.and(sc.entity().getType(), Op.EQ, type);
+ }
+ if (clusterId != null) {
+ sc.and(sc.entity().getClusterId(), Op.EQ, clusterId);
+ }
+ if (podId != null) {
+ sc.and(sc.entity().getPodId(), Op.EQ, podId);
+ }
+ sc.and(sc.entity().getDataCenterId(), Op.EQ, dcId);
+ sc.and(sc.entity().getStatus(), Op.EQ, Status.Up);
+ return sc.list();
+ }
+
@Override
public List<HostVO> listAllUpAndEnabledNonHAHosts(final Type type, final Long clusterId, final Long podId, final long dcId) {
final String haTag = _haMgr.getHaTag();
diff --git a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java
index 25afd0115ea..55ed60b3804 100644
--- a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java
+++ b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java
@@ -26,9 +26,12 @@
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
+import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.Configurable;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@@ -83,7 +86,6 @@
import com.cloud.user.AccountVO;
import com.cloud.user.ResourceLimitService;
import com.cloud.user.dao.AccountDao;
-import com.cloud.utils.NumbersUtil;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.DB;
@@ -107,7 +109,8 @@
import com.cloud.vm.dao.VMInstanceDao;
@Component
-public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLimitService {
+@Local(value = {ResourceLimitService.class})
+public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLimitService, Configurable{
public static final Logger s_logger = Logger.getLogger(ResourceLimitManagerImpl.class);
@Inject
@@ -205,7 +208,7 @@ public boolean configure(final String name, final Map<String, Object> params) th
snapshotSizeSearch.join("snapshots", join2, snapshotSizeSearch.entity().getSnapshotId(), join2.entity().getId(), JoinBuilder.JoinType.INNER);
snapshotSizeSearch.done();
- _resourceCountCheckInterval = NumbersUtil.parseInt(_configDao.getValue(Config.ResourceCountCheckInterval.key()), 0);
+ _resourceCountCheckInterval = ResourceCountCheckInterval.value();
if (_resourceCountCheckInterval > 0) {
_rcExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("ResourceCountChecker"));
}
@@ -1061,6 +1064,16 @@ public void changeResourceCount(long accountId, ResourceType type, Boolean displ
}
}
+ @Override
+ public String getConfigComponentName() {
+ return ResourceLimitManagerImpl.class.getName();
+ }
+
+ @Override
+ public ConfigKey<?>[] getConfigKeys() {
+ return new ConfigKey<?>[] {ResourceCountCheckInterval};
+ }
+
protected class ResourceCountCheckTask extends ManagedContextRunnable {
public ResourceCountCheckTask() {
diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java
index c94d92c85dc..27172b47bbc 100644
--- a/server/src/com/cloud/server/ConfigurationServerImpl.java
+++ b/server/src/com/cloud/server/ConfigurationServerImpl.java
@@ -23,8 +23,6 @@
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
import java.security.NoSuchAlgorithmException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -36,24 +34,21 @@
import java.util.Properties;
import java.util.Set;
import java.util.UUID;
-import java.util.regex.Pattern;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
-import org.apache.commons.codec.binary.Base64;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang.StringUtils;
-import org.apache.log4j.Logger;
-
import org.apache.cloudstack.config.ApiServiceConfiguration;
import org.apache.cloudstack.framework.config.ConfigDepot;
import org.apache.cloudstack.framework.config.ConfigDepotAdmin;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.framework.config.impl.ConfigurationVO;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
import com.cloud.configuration.Config;
import com.cloud.configuration.ConfigurationManager;
@@ -117,7 +112,6 @@
import com.cloud.utils.db.TransactionStatus;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
-import com.cloud.utils.nio.Link;
import com.cloud.utils.script.Script;
public class ConfigurationServerImpl extends ManagerBase implements ConfigurationServer {
@@ -306,9 +300,6 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
// Update resource count if needed
updateResourceCount();
- // keystore for SSL/TLS connection
- updateSSLKeystore();
-
// store the public and private keys in the database
updateKeyPairs();
@@ -544,117 +535,6 @@ protected void updateCloudIdentifier() {
}
}
- static String getBase64Keystore(String keystorePath) throws IOException {
- byte[] storeBytes = FileUtils.readFileToByteArray(new File(keystorePath));
- if (storeBytes.length > 3000) { // Base64 codec would enlarge data by 1/3, and we have 4094 bytes in database entry at most
- throw new IOException("KeyStore is too big for database! Length " + storeBytes.length);
- }
-
- return new String(Base64.encodeBase64(storeBytes));
- }
-
- private void generateDefaultKeystore(String keystorePath) throws IOException {
- String cn = "Cloudstack User";
- String ou;
-
- try {
- ou = InetAddress.getLocalHost().getCanonicalHostName();
- String[] group = ou.split("\\.");
-
- // Simple check to see if we got IP Address...
- boolean isIPAddress = Pattern.matches("[0-9]$", group[group.length - 1]);
- if (isIPAddress) {
- ou = "cloud.com"; // leaving this example reference to cloud.com as it has no real world relevance
- } else {
- ou = group[group.length - 1];
- for (int i = group.length - 2; i >= 0 && i >= group.length - 3; i--)
- ou = group[i] + "." + ou;
- }
- } catch (UnknownHostException ex) {
- s_logger.info("Fail to get user's domain name. Would use cloud.com. ", ex);
- ou = "cloud.com"; // leaving this example reference to cloud.com as it has no real world relevance
- }
-
- String o = ou;
- String c = "Unknown";
- String dname = "cn=\"" + cn + "\",ou=\"" + ou + "\",o=\"" + o + "\",c=\"" + c + "\"";
- Script script = new Script(true, "keytool", 5000, null);
- script.add("-genkey");
- script.add("-keystore", keystorePath);
- script.add("-storepass", "vmops.com");
- script.add("-keypass", "vmops.com");
- script.add("-keyalg", "RSA");
- script.add("-validity", "3650");
- script.add("-dname", dname);
- String result = script.execute();
- if (result != null) {
- throw new IOException("Fail to generate certificate!: " + result);
- }
- }
-
- protected void updateSSLKeystore() {
- if (s_logger.isInfoEnabled()) {
- s_logger.info("Processing updateSSLKeyStore");
- }
-
- String dbString = _configDao.getValue("ssl.keystore");
-
- File confFile = PropertiesUtil.findConfigFile("db.properties");
- String confPath = null;
- String keystorePath = null;
- File keystoreFile = null;
-
- if (null != confFile) {
- confPath = confFile.getParent();
- keystorePath = confPath + Link.keystoreFile;
- keystoreFile = new File(keystorePath);
- }
-
- boolean dbExisted = (dbString != null && !dbString.isEmpty());
-
- s_logger.info("SSL keystore located at " + keystorePath);
- try {
- if (!dbExisted && null != confFile) {
- if (!keystoreFile.exists()) {
- generateDefaultKeystore(keystorePath);
- s_logger.info("Generated SSL keystore.");
- }
- String base64Keystore = getBase64Keystore(keystorePath);
- ConfigurationVO configVO =
- new ConfigurationVO("Hidden", "DEFAULT", "management-server", "ssl.keystore", base64Keystore,
- "SSL Keystore for the management servers");
- _configDao.persist(configVO);
- s_logger.info("Stored SSL keystore to database.");
- } else { // !keystoreFile.exists() and dbExisted
- // Export keystore to local file
- byte[] storeBytes = Base64.decodeBase64(dbString);
- String tmpKeystorePath = "/tmp/tmpkey";
- try (
- FileOutputStream fo = new FileOutputStream(tmpKeystorePath);
- ) {
- fo.write(storeBytes);
- Script script = new Script(true, "cp", 5000, null);
- script.add("-f");
- script.add(tmpKeystorePath);
-
- //There is a chance, although small, that the keystorePath is null. In that case, do not add it to the script.
- if (null != keystorePath) {
- script.add(keystorePath);
- }
- String result = script.execute();
- if (result != null) {
- throw new IOException();
- }
- } catch (Exception e) {
- throw new IOException("Fail to create keystore file!", e);
- }
- s_logger.info("Stored database keystore to local.");
- }
- } catch (Exception ex) {
- s_logger.warn("Would use fail-safe keystore to continue.", ex);
- }
- }
-
@DB
protected void updateSystemvmPassword() {
String userid = System.getProperty("user.name");
diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java
index fa513be4614..da987ca1330 100644
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -48,8 +48,10 @@
import org.apache.cloudstack.api.command.admin.account.ListAccountsCmdByAdmin;
import org.apache.cloudstack.api.command.admin.account.LockAccountCmd;
import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd;
+import org.apache.cloudstack.api.command.admin.address.AcquirePodIpCmdByAdmin;
import org.apache.cloudstack.api.command.admin.address.AssociateIPAddrCmdByAdmin;
import org.apache.cloudstack.api.command.admin.address.ListPublicIpAddressesCmdByAdmin;
+import org.apache.cloudstack.api.command.admin.address.ReleasePodIpCmdByAdmin;
import org.apache.cloudstack.api.command.admin.affinitygroup.UpdateVMAffinityGroupCmdByAdmin;
import org.apache.cloudstack.api.command.admin.alert.GenerateAlertCmd;
import org.apache.cloudstack.api.command.admin.autoscale.CreateCounterCmd;
@@ -1430,7 +1432,7 @@ private boolean hasSuitablePoolsForVolume(final VolumeVO volume, final Host host
sb.and("clusterId", sb.entity().getClusterId(), SearchCriteria.Op.EQ);
sb.and("resourceState", sb.entity().getResourceState(), SearchCriteria.Op.EQ);
sb.and("hypervisorType", sb.entity().getHypervisorType(), SearchCriteria.Op.EQ);
- sb.and("hypervisorVersion", sb.entity().getHypervisorVersion(), SearchCriteria.Op.EQ);
+ sb.and("hypervisorVersion", sb.entity().getHypervisorVersion(), SearchCriteria.Op.GTEQ);
final String haTag = _haMgr.getHaTag();
SearchBuilder<HostTagVO> hostTagSearch = null;
@@ -1752,7 +1754,7 @@ private boolean hasSuitablePoolsForVolume(final VolumeVO volume, final Host host
if (configVo != null) {
final ConfigKey<?> key = _configDepot.get(param.getName());
if (key != null) {
- configVo.setValue(key.valueIn(id).toString());
+ configVo.setValue(key.valueIn(id) == null ? null : key.valueIn(id).toString());
configVOList.add(configVo);
} else {
s_logger.warn("ConfigDepot could not find parameter " + param.getName() + " for scope " + scope);
@@ -2503,6 +2505,7 @@ public int compare(final SummedCapacity arg0, final SummedCapacity arg1) {
for (final SummedCapacity summedCapacity : summedCapacities) {
final CapacityVO capacity = new CapacityVO(null, summedCapacity.getDataCenterId(),summedCapacity.getPodId(), summedCapacity.getClusterId(), summedCapacity.getUsedCapacity()
+ summedCapacity.getReservedCapacity(), summedCapacity.getTotalCapacity(), summedCapacity.getCapacityType());
+ capacity.setAllocatedCapacity(summedCapacity.getAllocatedCapacity());
capacities.add(capacity);
}
@@ -3019,6 +3022,9 @@ public long getMemoryOrCpuCapacityByHost(final Long hostId, final short capacity
cmdList.add(ChangeOutOfBandManagementPasswordCmd.class);
cmdList.add(GetUserKeysCmd.class);
+ cmdList.add(AcquirePodIpCmdByAdmin.class);
+ cmdList.add(ReleasePodIpCmdByAdmin.class);
+
return cmdList;
}
diff --git a/server/src/com/cloud/server/StatsCollector.java b/server/src/com/cloud/server/StatsCollector.java
index 58d9d33f447..048b3b1e3e2 100644
--- a/server/src/com/cloud/server/StatsCollector.java
+++ b/server/src/com/cloud/server/StatsCollector.java
@@ -20,7 +20,6 @@
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Calendar;
-import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@@ -34,19 +33,12 @@
import javax.inject.Inject;
-import org.apache.cloudstack.outofbandmanagement.OutOfBandManagement;
-import org.apache.cloudstack.outofbandmanagement.OutOfBandManagementService;
-import org.apache.cloudstack.outofbandmanagement.OutOfBandManagementVO;
-import org.apache.cloudstack.outofbandmanagement.dao.OutOfBandManagementDao;
-import org.apache.cloudstack.utils.identity.ManagementServerNode;
-import org.apache.cloudstack.utils.usage.UsageUtils;
-import org.apache.commons.lang.StringUtils;
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
@@ -54,6 +46,10 @@
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.utils.graphite.GraphiteClient;
import org.apache.cloudstack.utils.graphite.GraphiteException;
+import org.apache.cloudstack.utils.usage.UsageUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
@@ -62,9 +58,13 @@
import com.cloud.agent.api.PerformanceMonitorCommand;
import com.cloud.agent.api.VgpuTypesInfo;
import com.cloud.agent.api.VmDiskStatsEntry;
+import com.cloud.agent.api.VmNetworkStatsEntry;
import com.cloud.agent.api.VmStatsEntry;
import com.cloud.cluster.ManagementServerHostVO;
import com.cloud.cluster.dao.ManagementServerHostDao;
+import com.cloud.dc.Vlan.VlanType;
+import com.cloud.dc.VlanVO;
+import com.cloud.dc.dao.VlanDao;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.gpu.dao.HostGpuGroupsDao;
import com.cloud.host.Host;
@@ -103,7 +103,9 @@
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.VolumeDao;
+import com.cloud.user.UserStatisticsVO;
import com.cloud.user.VmDiskStatisticsVO;
+import com.cloud.user.dao.UserStatisticsDao;
import com.cloud.user.dao.VmDiskStatisticsDao;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
@@ -117,11 +119,13 @@
import com.cloud.utils.db.TransactionCallbackNoReturn;
import com.cloud.utils.db.TransactionStatus;
import com.cloud.utils.net.MacAddress;
+import com.cloud.vm.NicVO;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VmStats;
+import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
@@ -130,7 +134,7 @@
*
*/
@Component
-public class StatsCollector extends ManagerBase implements ComponentMethodInterceptable {
+public class StatsCollector extends ManagerBase implements ComponentMethodInterceptable, Configurable {
public static enum ExternalStatsProtocol {
NONE("none"), GRAPHITE("graphite");
@@ -148,6 +152,15 @@ public String toString() {
public static final Logger s_logger = Logger.getLogger(StatsCollector.class.getName());
+ static final ConfigKey<Integer> vmDiskStatsInterval = new ConfigKey<Integer>("Advanced", Integer.class, "vm.disk.stats.interval", "0",
+ "Interval (in seconds) to report vm disk statistics. Vm disk statistics will be disabled if this is set to 0 or less than 0.", false);
+ static final ConfigKey<Integer> vmDiskStatsIntervalMin = new ConfigKey<Integer>("Advanced", Integer.class, "vm.disk.stats.interval.min", "300",
+ "Minimal interval (in seconds) to report vm disk statistics. If vm.disk.stats.interval is smaller than this, use this to report vm disk statistics.", false);
+ static final ConfigKey<Integer> vmNetworkStatsInterval = new ConfigKey<Integer>("Advanced", Integer.class, "vm.network.stats.interval", "0",
+ "Interval (in seconds) to report vm network statistics (for Shared networks). Vm network statistics will be disabled if this is set to 0 or less than 0.", false);
+ static final ConfigKey<Integer> vmNetworkStatsIntervalMin = new ConfigKey<Integer>("Advanced", Integer.class, "vm.network.stats.interval.min", "300",
+ "Minimal Interval (in seconds) to report vm network statistics (for Shared networks). If vm.network.stats.interval is smaller than this, use this to report vm network statistics.", false);
+
private static StatsCollector s_instance = null;
private ScheduledExecutorService _executor = null;
@@ -158,8 +171,6 @@ public String toString() {
@Inject
private HostDao _hostDao;
@Inject
- private OutOfBandManagementDao outOfBandManagementDao;
- @Inject
private UserVmDao _userVmDao;
@Inject
private VolumeDao _volsDao;
@@ -176,8 +187,6 @@ public String toString() {
@Inject
private ResourceManager _resourceMgr;
@Inject
- private OutOfBandManagementService outOfBandManagementService;
- @Inject
private ConfigurationDao _configDao;
@Inject
private EndPointSelector _epSelector;
@@ -186,6 +195,12 @@ public String toString() {
@Inject
private ManagementServerHostDao _msHostDao;
@Inject
+ private UserStatisticsDao _userStatsDao;
+ @Inject
+ private NicDao _nicDao;
+ @Inject
+ private VlanDao _vlanDao;
+ @Inject
private AutoScaleVmGroupDao _asGroupDao;
@Inject
private AutoScaleVmGroupVmMapDao _asGroupVmDao;
@@ -219,12 +234,11 @@ public String toString() {
private ConcurrentHashMap<Long, StorageStats> _storagePoolStats = new ConcurrentHashMap<Long, StorageStats>();
long hostStatsInterval = -1L;
- long hostOutOfBandManagementStatsInterval = -1L;
long hostAndVmStatsInterval = -1L;
long storageStatsInterval = -1L;
long volumeStatsInterval = -1L;
long autoScaleStatsInterval = -1L;
- int vmDiskStatsInterval = 0;
+
List<Long> hostIds = null;
private double _imageStoreCapacityThreshold = 0.90;
@@ -265,13 +279,11 @@ public boolean start() {
private void init(Map<String, String> configs) {
_executor = Executors.newScheduledThreadPool(6, new NamedThreadFactory("StatsCollector"));
- hostOutOfBandManagementStatsInterval = OutOfBandManagementService.SyncThreadInterval.value();
hostStatsInterval = NumbersUtil.parseLong(configs.get("host.stats.interval"), 60000L);
hostAndVmStatsInterval = NumbersUtil.parseLong(configs.get("vm.stats.interval"), 60000L);
storageStatsInterval = NumbersUtil.parseLong(configs.get("storage.stats.interval"), 60000L);
volumeStatsInterval = NumbersUtil.parseLong(configs.get("volume.stats.interval"), -1L);
autoScaleStatsInterval = NumbersUtil.parseLong(configs.get("autoscale.stats.interval"), 60000L);
- vmDiskStatsInterval = NumbersUtil.parseInt(configs.get("vm.disk.stats.interval"), 0);
/* URI to send statistics to. Currently only Graphite is supported */
String externalStatsUri = configs.get("stats.output.uri");
@@ -313,10 +325,6 @@ private void init(Map<String, String> configs) {
_executor.scheduleWithFixedDelay(new HostCollector(), 15000L, hostStatsInterval, TimeUnit.MILLISECONDS);
}
- if (hostOutOfBandManagementStatsInterval > 0) {
- _executor.scheduleWithFixedDelay(new HostOutOfBandManagementStatsCollector(), 15000L, hostOutOfBandManagementStatsInterval, TimeUnit.MILLISECONDS);
- }
-
if (hostAndVmStatsInterval > 0) {
_executor.scheduleWithFixedDelay(new VmStatsCollector(), 15000L, hostAndVmStatsInterval, TimeUnit.MILLISECONDS);
}
@@ -329,14 +337,31 @@ private void init(Map<String, String> configs) {
_executor.scheduleWithFixedDelay(new AutoScaleMonitor(), 15000L, autoScaleStatsInterval, TimeUnit.MILLISECONDS);
}
- if (vmDiskStatsInterval > 0) {
- if (vmDiskStatsInterval < 300)
- vmDiskStatsInterval = 300;
- _executor.scheduleAtFixedRate(new VmDiskStatsTask(), vmDiskStatsInterval, vmDiskStatsInterval, TimeUnit.SECONDS);
+ if (vmDiskStatsInterval.value() > 0) {
+ if (vmDiskStatsInterval.value() < vmDiskStatsIntervalMin.value()) {
+ s_logger.debug("vm.disk.stats.interval - " + vmDiskStatsInterval.value() + " is smaller than vm.disk.stats.interval.min - " + vmDiskStatsIntervalMin.value() + ", so use vm.disk.stats.interval.min");
+ _executor.scheduleAtFixedRate(new VmDiskStatsTask(), vmDiskStatsIntervalMin.value(), vmDiskStatsIntervalMin.value(), TimeUnit.SECONDS);
+ } else {
+ _executor.scheduleAtFixedRate(new VmDiskStatsTask(), vmDiskStatsInterval.value(), vmDiskStatsInterval.value(), TimeUnit.SECONDS);
+ }
+ } else {
+ s_logger.debug("vm.disk.stats.interval - " + vmDiskStatsInterval.value() + " is 0 or less than 0, so not scheduling the vm disk stats thread");
+ }
+
+ if (vmNetworkStatsInterval.value() > 0) {
+ if (vmNetworkStatsInterval.value() < vmNetworkStatsIntervalMin.value()) {
+ s_logger.debug("vm.network.stats.interval - " + vmNetworkStatsInterval.value() + " is smaller than vm.network.stats.interval.min - " + vmNetworkStatsIntervalMin.value() + ", so use vm.network.stats.interval.min");
+ _executor.scheduleAtFixedRate(new VmNetworkStatsTask(), vmNetworkStatsIntervalMin.value(), vmNetworkStatsIntervalMin.value(), TimeUnit.SECONDS);
+ } else {
+ _executor.scheduleAtFixedRate(new VmNetworkStatsTask(), vmNetworkStatsInterval.value(), vmNetworkStatsInterval.value(), TimeUnit.SECONDS);
+ }
+ } else {
+ s_logger.debug("vm.network.stats.interval - " + vmNetworkStatsInterval.value() + " is 0 or less than 0, so not scheduling the vm network stats thread");
}
//Schedule disk stats update task
_diskStatsUpdateExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("DiskStatsUpdater"));
+
String aggregationRange = configs.get("usage.stats.job.aggregation.range");
_usageAggregationRange = NumbersUtil.parseInt(aggregationRange, 1440);
_usageTimeZone = configs.get("usage.aggregation.timezone");
@@ -396,6 +421,7 @@ protected void runInContext() {
sc.addAnd("type", SearchCriteria.Op.NEQ, Host.Type.SecondaryStorageVM.toString());
sc.addAnd("type", SearchCriteria.Op.NEQ, Host.Type.ExternalFirewall.toString());
sc.addAnd("type", SearchCriteria.Op.NEQ, Host.Type.ExternalLoadBalancer.toString());
+ sc.addAnd("type", SearchCriteria.Op.NEQ, Host.Type.NetScalerControlCenter.toString());
sc.addAnd("type", SearchCriteria.Op.NEQ, Host.Type.L2Networking.toString());
sc.addAnd("type", SearchCriteria.Op.NEQ, Host.Type.BaremetalDhcp.toString());
sc.addAnd("type", SearchCriteria.Op.NEQ, Host.Type.BaremetalPxe.toString());
@@ -435,36 +461,6 @@ protected void runInContext() {
}
}
- class HostOutOfBandManagementStatsCollector extends ManagedContextRunnable {
- @Override
- protected void runInContext() {
- try {
- s_logger.trace("HostOutOfBandManagementStatsCollector is running...");
- List<OutOfBandManagementVO> outOfBandManagementHosts = outOfBandManagementDao.findAllByManagementServer(ManagementServerNode.getManagementServerId());
- if (outOfBandManagementHosts == null) {
- return;
- }
- for (OutOfBandManagement outOfBandManagementHost : outOfBandManagementHosts) {
- Host host = _hostDao.findById(outOfBandManagementHost.getHostId());
- if (host == null) {
- continue;
- }
- if (outOfBandManagementService.isOutOfBandManagementEnabled(host)) {
- outOfBandManagementService.submitBackgroundPowerSyncTask(host);
- } else if (outOfBandManagementHost.getPowerState() != OutOfBandManagement.PowerState.Disabled) {
- if (outOfBandManagementService.transitionPowerStateToDisabled(Collections.singletonList(host))) {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Out-of-band management was disabled in zone/cluster/host, disabled power state for host id:" + host.getId());
- }
- }
- }
- }
- } catch (Throwable t) {
- s_logger.error("Error trying to retrieve host out-of-band management stats", t);
- }
- }
- }
-
class VmStatsCollector extends ManagedContextRunnable {
@Override
protected void runInContext() {
@@ -640,11 +636,20 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
class VmDiskStatsTask extends ManagedContextRunnable {
@Override
protected void runInContext() {
+ //Check for ownership
+ //msHost in UP state with min id should run the job
+ ManagementServerHostVO msHost = _msHostDao.findOneInUpState(new Filter(ManagementServerHostVO.class, "id", true, 0L, 1L));
+ if(msHost == null || (msHost.getMsid() != mgmtSrvrId)){
+ s_logger.debug("Skipping collect vm disk stats from hosts");
+ return;
+ }
// collect the vm disk statistics(total) from hypervisor. added by weizhou, 2013.03.
try {
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
+ s_logger.debug("VmDiskStatsTask is running...");
+
SearchCriteria<HostVO> sc = _hostDao.createSearchCriteria();
sc.addAnd("status", SearchCriteria.Op.EQ, Status.Up.toString());
sc.addAnd("resourceState", SearchCriteria.Op.NIN, ResourceState.Maintenance, ResourceState.PrepareForMaintenance,
@@ -762,6 +767,126 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
}
}
+ class VmNetworkStatsTask extends ManagedContextRunnable {
+ @Override
+ protected void runInContext() {
+ //Check for ownership
+ //msHost in UP state with min id should run the job
+ ManagementServerHostVO msHost = _msHostDao.findOneInUpState(new Filter(ManagementServerHostVO.class, "id", true, 0L, 1L));
+ if(msHost == null || (msHost.getMsid() != mgmtSrvrId)){
+ s_logger.debug("Skipping collect vm network stats from hosts");
+ return;
+ }
+ // collect the vm network statistics(total) from hypervisor
+ try {
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ s_logger.debug("VmNetworkStatsTask is running...");
+
+ SearchCriteria<HostVO> sc = _hostDao.createSearchCriteria();
+ sc.addAnd("status", SearchCriteria.Op.EQ, Status.Up.toString());
+ sc.addAnd("resourceState", SearchCriteria.Op.NIN, ResourceState.Maintenance, ResourceState.PrepareForMaintenance, ResourceState.ErrorInMaintenance);
+ sc.addAnd("type", SearchCriteria.Op.EQ, Host.Type.Routing.toString());
+ List<HostVO> hosts = _hostDao.search(sc, null);
+
+ for (HostVO host : hosts)
+ {
+ List<UserVmVO> vms = _userVmDao.listRunningByHostId(host.getId());
+ List<Long> vmIds = new ArrayList<Long>();
+
+ for (UserVmVO vm : vms) {
+ if (vm.getType() == VirtualMachine.Type.User) // user vm
+ vmIds.add(vm.getId());
+ }
+
+ HashMap<Long, List<VmNetworkStatsEntry>> vmNetworkStatsById = _userVmMgr.getVmNetworkStatistics(host.getId(), host.getName(), vmIds);
+ if (vmNetworkStatsById == null)
+ continue;
+
+ Set<Long> vmIdSet = vmNetworkStatsById.keySet();
+ for(Long vmId : vmIdSet)
+ {
+ List<VmNetworkStatsEntry> vmNetworkStats = vmNetworkStatsById.get(vmId);
+ if (vmNetworkStats == null)
+ continue;
+ UserVmVO userVm = _userVmDao.findById(vmId);
+ if (userVm == null) {
+ s_logger.debug("Cannot find uservm with id: " + vmId + " , continue");
+ continue;
+ }
+ s_logger.debug("Now we are updating the user_statistics table for VM: " + userVm.getInstanceName() + " after collecting vm network statistics from host: " + host.getName());
+ for (VmNetworkStatsEntry vmNetworkStat:vmNetworkStats) {
+ SearchCriteria<NicVO> sc_nic = _nicDao.createSearchCriteria();
+ sc_nic.addAnd("macAddress", SearchCriteria.Op.EQ, vmNetworkStat.getMacAddress());
+ NicVO nic = _nicDao.search(sc_nic, null).get(0);
+ List<VlanVO> vlan = _vlanDao.listVlansByNetworkId(nic.getNetworkId());
+ if (vlan == null || vlan.size() == 0 || vlan.get(0).getVlanType() != VlanType.DirectAttached)
+ continue; // only get network statistics for DirectAttached network (shared networks in Basic zone and Advanced zone with/without SG)
+ UserStatisticsVO previousvmNetworkStats = _userStatsDao.findBy(userVm.getAccountId(), userVm.getDataCenterId(), nic.getNetworkId(), nic.getIPv4Address(), vmId, "UserVm");
+ if (previousvmNetworkStats == null) {
+ previousvmNetworkStats = new UserStatisticsVO(userVm.getAccountId(), userVm.getDataCenterId(),nic.getIPv4Address(), vmId, "UserVm", nic.getNetworkId());
+ _userStatsDao.persist(previousvmNetworkStats);
+ }
+ UserStatisticsVO vmNetworkStat_lock = _userStatsDao.lock(userVm.getAccountId(), userVm.getDataCenterId(), nic.getNetworkId(), nic.getIPv4Address(), vmId, "UserVm");
+
+ if ((vmNetworkStat.getBytesSent() == 0) && (vmNetworkStat.getBytesReceived() == 0)) {
+ s_logger.debug("bytes sent and received are all 0. Not updating user_statistics");
+ continue;
+ }
+
+ if (vmNetworkStat_lock == null) {
+ s_logger.warn("unable to find vm network stats from host for account: " + userVm.getAccountId() + " with vmId: " + userVm.getId()+ " and nicId:" + nic.getId());
+ continue;
+ }
+
+ if (previousvmNetworkStats != null
+ && ((previousvmNetworkStats.getCurrentBytesSent() != vmNetworkStat_lock.getCurrentBytesSent())
+ || (previousvmNetworkStats.getCurrentBytesReceived() != vmNetworkStat_lock.getCurrentBytesReceived()))) {
+ s_logger.debug("vm network stats changed from the time GetNmNetworkStatsCommand was sent. " +
+ "Ignoring current answer. Host: " + host.getName() + " . VM: " + vmNetworkStat.getVmName() +
+ " Sent(Bytes): " + vmNetworkStat.getBytesSent() + " Received(Bytes): " + vmNetworkStat.getBytesReceived());
+ continue;
+ }
+
+ if (vmNetworkStat_lock.getCurrentBytesSent() > vmNetworkStat.getBytesSent()) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Sent # of bytes that's less than the last one. " +
+ "Assuming something went wrong and persisting it. Host: " + host.getName() + " . VM: " + vmNetworkStat.getVmName() +
+ " Reported: " + vmNetworkStat.getBytesSent() + " Stored: " + vmNetworkStat_lock.getCurrentBytesSent());
+ }
+ vmNetworkStat_lock.setNetBytesSent(vmNetworkStat_lock.getNetBytesSent() + vmNetworkStat_lock.getCurrentBytesSent());
+ }
+ vmNetworkStat_lock.setCurrentBytesSent(vmNetworkStat.getBytesSent());
+
+ if (vmNetworkStat_lock.getCurrentBytesReceived() > vmNetworkStat.getBytesReceived()) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Received # of bytes that's less than the last one. " +
+ "Assuming something went wrong and persisting it. Host: " + host.getName() + " . VM: " + vmNetworkStat.getVmName() +
+ " Reported: " + vmNetworkStat.getBytesReceived() + " Stored: " + vmNetworkStat_lock.getCurrentBytesReceived());
+ }
+ vmNetworkStat_lock.setNetBytesReceived(vmNetworkStat_lock.getNetBytesReceived() + vmNetworkStat_lock.getCurrentBytesReceived());
+ }
+ vmNetworkStat_lock.setCurrentBytesReceived(vmNetworkStat.getBytesReceived());
+
+ if (! _dailyOrHourly) {
+ //update agg bytes
+ vmNetworkStat_lock.setAggBytesReceived(vmNetworkStat_lock.getNetBytesReceived() + vmNetworkStat_lock.getCurrentBytesReceived());
+ vmNetworkStat_lock.setAggBytesSent(vmNetworkStat_lock.getNetBytesSent() + vmNetworkStat_lock.getCurrentBytesSent());
+ }
+
+ _userStatsDao.update(vmNetworkStat_lock.getId(), vmNetworkStat_lock);
+ }
+ }
+ }
+ }
+ });
+ } catch (Exception e) {
+ s_logger.warn("Error while collecting vm network stats from hosts", e);
+ }
+ }
+ }
+
class StorageCollector extends ManagedContextRunnable {
@Override
protected void runInContext() {
@@ -1129,4 +1254,14 @@ public HostStats getHostStats(long hostId) {
public StorageStats getStoragePoolStats(long id) {
return _storagePoolStats.get(id);
}
+
+ @Override
+ public String getConfigComponentName() {
+ return this.getClass().getSimpleName();
+ }
+
+ @Override
+ public ConfigKey<?>[] getConfigKeys() {
+ return new ConfigKey<?>[] { vmDiskStatsInterval, vmDiskStatsIntervalMin, vmNetworkStatsInterval, vmNetworkStatsIntervalMin };
+ }
}
diff --git a/server/src/com/cloud/servlet/StaticResourceServlet.java b/server/src/com/cloud/servlet/StaticResourceServlet.java
deleted file mode 100644
index 8e96732e4ff..00000000000
--- a/server/src/com/cloud/servlet/StaticResourceServlet.java
+++ /dev/null
@@ -1,115 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.servlet;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang.StringUtils;
-
-/**
- * Serves static resources with support for gzip compression and content
- * caching.
- */
-public class StaticResourceServlet extends HttpServlet {
-
- private static final long serialVersionUID = -8833228931973461812L;
-
- private File getRequestedFile(final HttpServletRequest req) {
- return new File(getServletContext().getRealPath(req.getServletPath()));
- }
-
- @Override
- protected void doGet(final HttpServletRequest req,
- final HttpServletResponse resp) throws ServletException,
- IOException {
- final File requestedFile = getRequestedFile(req);
- if (!requestedFile.exists() || !requestedFile.isFile()) {
- resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
- return;
- }
- final String etag = getEtag(requestedFile);
- if (etag.equals(req.getHeader("If-None-Match"))) {
- resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
- return;
- }
- // have to send data, either compressed or the original
- final File compressedStatic = getCompressedVersion(requestedFile);
- InputStream fileContent = null;
- try {
- resp.setContentType(getContentType(requestedFile.getName()));
- resp.setHeader("ETag", etag);
- resp.setStatus(HttpServletResponse.SC_OK);
- if (isClientCompressionSupported(req) && compressedStatic.exists()) {
- // gzip compressed
- resp.setHeader("Content-Encoding", "gzip");
- resp.setContentLength((int) compressedStatic.length());
- fileContent = new FileInputStream(compressedStatic);
- } else {
- // uncompressed
- resp.setContentLength((int) requestedFile.length());
- fileContent = new FileInputStream(requestedFile);
- }
- IOUtils.copy(fileContent, resp.getOutputStream());
- } finally {
- IOUtils.closeQuietly(fileContent);
- }
- }
-
- @SuppressWarnings("serial")
- static final Map<String, String> contentTypes = Collections
- .unmodifiableMap(new HashMap<String, String>() {
- {
- put("css", "text/css");
- put("svg", "image/svg+xml");
- put("js", "application/javascript");
- put("htm", "text/html");
- put("html", "text/html");
- put("txt", "text/plain");
- put("xml", "text/xml");
- }
- });
-
- static String getContentType(final String fileName) {
- return contentTypes.get(StringUtils.lowerCase(StringUtils
- .substringAfterLast(fileName, ".")));
- }
-
- static File getCompressedVersion(final File requestedFile) {
- return new File(requestedFile.getAbsolutePath() + ".gz");
- }
-
- static boolean isClientCompressionSupported(final HttpServletRequest req) {
- return StringUtils.contains(req.getHeader("Accept-Encoding"), "gzip");
- }
-
- static String getEtag(final File resource) {
- return "W/\"" + resource.length() + "-" + resource.lastModified();
- }
-
-}
diff --git a/server/src/com/cloud/storage/CreateSnapshotPayload.java b/server/src/com/cloud/storage/CreateSnapshotPayload.java
index 3e9368d8c6f..b0bb9eafb2e 100644
--- a/server/src/com/cloud/storage/CreateSnapshotPayload.java
+++ b/server/src/com/cloud/storage/CreateSnapshotPayload.java
@@ -24,6 +24,7 @@
private Account account;
private boolean quiescevm;
private Snapshot.LocationType locationType;
+ private boolean asyncBackup;
public Long getSnapshotPolicyId() {
return snapshotPolicyId;
@@ -58,4 +59,12 @@ public boolean getQuiescevm() {
public Snapshot.LocationType getLocationType() { return this.locationType; }
public void setLocationType(Snapshot.LocationType locationType) { this.locationType = locationType; }
+
+ public void setAsyncBackup(boolean asyncBackup) {
+ this.asyncBackup = asyncBackup;
+ }
+
+ public boolean getAsyncBackup() {
+ return this.asyncBackup;
+ }
}
diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java
index a8a38ba74c5..ac20f0f36ee 100644
--- a/server/src/com/cloud/storage/StorageManagerImpl.java
+++ b/server/src/com/cloud/storage/StorageManagerImpl.java
@@ -314,7 +314,6 @@ public void setDiscoverers(List<StoragePoolDiscoverer> discoverers) {
protected SearchBuilder<StoragePoolVO> LocalStorageSearch;
ScheduledExecutorService _executor = null;
- boolean _templateCleanupEnabled = true;
int _storagePoolAcquisitionWaitSeconds = 1800; // 30 minutes
int _downloadUrlCleanupInterval;
int _downloadUrlExpirationInterval;
@@ -477,11 +476,8 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
_agentMgr.registerForHostEvents(new StoragePoolMonitor(this, _storagePoolDao, _dataStoreProviderMgr), true, false, true);
- String value = _configDao.getValue(Config.StorageTemplateCleanupEnabled.key());
- _templateCleanupEnabled = (value == null ? true : Boolean.parseBoolean(value));
-
s_logger.info("Storage cleanup enabled: " + StorageCleanupEnabled.value() + ", interval: " + StorageCleanupInterval.value() + ", delay: " + StorageCleanupDelay.value() +
- ", template cleanup enabled: " + _templateCleanupEnabled);
+ ", template cleanup enabled: " + TemplateCleanupEnabled.value());
String cleanupInterval = configs.get("extract.url.cleanup.interval");
_downloadUrlCleanupInterval = NumbersUtil.parseInt(cleanupInterval, 7200);
@@ -1036,7 +1032,6 @@ public void createCapacityEntry(StoragePoolVO storagePool, short capacityType, l
Command[] cmdArray = cmds.toCommands();
for (Command cmd : cmdArray) {
long targetHostId = _hvGuruMgr.getGuruProcessedCommandTargetHost(hostId, cmd);
-
answers.add(_agentMgr.send(targetHostId, cmd));
}
return new Pair<Long, Answer[]>(hostId, answers.toArray(new Answer[answers.size()]));
@@ -1065,7 +1060,7 @@ public void cleanupStorage(boolean recurring) {
if (scanLock.lock(3)) {
try {
// Cleanup primary storage pools
- if (_templateCleanupEnabled) {
+ if (TemplateCleanupEnabled.value()) {
List<StoragePoolVO> storagePools = _storagePoolDao.listAll();
for (StoragePoolVO pool : storagePools) {
try {
@@ -2351,8 +2346,6 @@ public void cleanupDownloadUrls(){
" for template id " +templateOnImageStore.getTemplateId(), th);
}
}
-
-
}
// get bytesReadRate from service_offering, disk_offering and vm.disk.throttling.bytes_read_rate
@@ -2426,7 +2419,7 @@ public String getConfigComponentName() {
@Override
public ConfigKey<?>[] getConfigKeys() {
- return new ConfigKey<?>[] {StorageCleanupInterval, StorageCleanupDelay, StorageCleanupEnabled};
+ return new ConfigKey<?>[] {StorageCleanupInterval, StorageCleanupDelay, StorageCleanupEnabled, TemplateCleanupEnabled};
}
@Override
diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
index 98fd1a327ca..37b72a68d14 100644
--- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
@@ -84,6 +84,7 @@
import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.utils.fsm.StateMachine2;
import com.cloud.vm.UserVmManager;
+import com.cloud.vm.UserVmService;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
@@ -108,6 +109,7 @@
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonParseException;
+
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
@@ -162,6 +164,7 @@
import org.joda.time.DateTimeZone;
import javax.inject.Inject;
+
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
@@ -205,6 +208,8 @@
@Inject
UserVmDao _userVmDao;
@Inject
+ UserVmService _userVmService;
+ @Inject
VolumeDataStoreDao _volumeStoreDao;
@Inject
VMInstanceDao _vmInstanceDao;
@@ -257,6 +262,10 @@
static final ConfigKey<Long> VmJobCheckInterval = new ConfigKey<Long>("Advanced", Long.class, "vm.job.check.interval", "3000",
"Interval in milliseconds to check if the job is complete", false);
+ static final ConfigKey<Boolean> VolumeUrlCheck = new ConfigKey<Boolean>("Advanced", Boolean.class, "volume.url.check", "true",
+ "Check the url for a volume before downloading it from the management server. Set to false when you managment has no internet access.",
+ true);
+
private long _maxVolumeSizeInGb;
private final StateMachine2<Volume.State, Volume.Event, Volume> _volStateMachine;
@@ -400,8 +409,10 @@ private boolean validateVolume(Account caller, long ownerId, Long zoneId, String
throw new InvalidParameterValueException("File:// type urls are currently unsupported");
}
UriUtils.validateUrl(format, url);
- // check URL existence
- UriUtils.checkUrlExistence(url);
+ if (VolumeUrlCheck.value()) { // global setting that can be set when their MS does not have internet access
+ s_logger.debug("Checking url: " + url);
+ UriUtils.checkUrlExistence(url);
+ }
// Check that the resource limit for secondary storage won't be exceeded
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(ownerId), ResourceType.secondary_storage, UriUtils.getRemoteSize(url));
} else {
@@ -841,11 +852,16 @@ public VolumeVO resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationExcep
boolean shrinkOk = cmd.getShrinkOk();
VolumeVO volume = _volsDao.findById(cmd.getEntityId());
-
if (volume == null) {
throw new InvalidParameterValueException("No such volume");
}
+ // checking if there are any ongoing snapshots on the volume which is to be resized
+ List<SnapshotVO> ongoingSnapshots = _snapshotDao.listByStatus(cmd.getId(), Snapshot.State.Creating, Snapshot.State.CreatedOnPrimary, Snapshot.State.BackingUp);
+ if (ongoingSnapshots.size() > 0) {
+ throw new CloudRuntimeException("There is/are unbacked up snapshot(s) on this volume, resize volume is not permitted, please try again later.");
+ }
+
/* Does the caller have authority to act on this volume? */
_accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, volume);
@@ -1799,6 +1815,12 @@ private Volume orchestrateDetachVolumeFromVM(long vmId, long volumeId) {
Answer answer = null;
if (sendCommand) {
+ // collect vm disk statistics before detach a volume
+ UserVmVO userVm = _userVmDao.findById(vmId);
+ if (userVm != null && userVm.getType() == VirtualMachine.Type.User) {
+ _userVmService.collectVmDiskStatistics(userVm);
+ }
+
DataTO volTO = volFactory.getVolume(volume.getId()).getTO();
DiskTO disk = new DiskTO(volTO, volume.getDeviceId(), volume.getPath(), volume.getVolumeType());
@@ -2052,7 +2074,7 @@ protected Volume liveMigrateVolume(Volume volume, StoragePool destPool) throws S
@Override
@ActionEvent(eventType = EventTypes.EVENT_SNAPSHOT_CREATE, eventDescription = "taking snapshot", async = true)
- public Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account, boolean quiescevm, Snapshot.LocationType locationType)
+ public Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account, boolean quiescevm, Snapshot.LocationType locationType, boolean asyncBackup)
throws ResourceAllocationException {
VolumeInfo volume = volFactory.getVolume(volumeId);
if (volume == null) {
@@ -2081,13 +2103,13 @@ public Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Acco
VmWorkJobVO placeHolder = null;
placeHolder = createPlaceHolderWork(vm.getId());
try {
- return orchestrateTakeVolumeSnapshot(volumeId, policyId, snapshotId, account, quiescevm, locationType);
+ return orchestrateTakeVolumeSnapshot(volumeId, policyId, snapshotId, account, quiescevm, locationType, asyncBackup);
} finally {
_workJobDao.expunge(placeHolder.getId());
}
} else {
- Outcome<Snapshot> outcome = takeVolumeSnapshotThroughJobQueue(vm.getId(), volumeId, policyId, snapshotId, account.getId(), quiescevm, locationType);
+ Outcome<Snapshot> outcome = takeVolumeSnapshotThroughJobQueue(vm.getId(), volumeId, policyId, snapshotId, account.getId(), quiescevm, locationType, asyncBackup);
try {
outcome.get();
@@ -2115,13 +2137,14 @@ else if (jobResult instanceof Throwable)
payload.setSnapshotPolicyId(policyId);
payload.setAccount(account);
payload.setQuiescevm(quiescevm);
+ payload.setAsyncBackup(asyncBackup);
volume.addPayload(payload);
return volService.takeSnapshot(volume);
}
}
private Snapshot orchestrateTakeVolumeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account,
- boolean quiescevm, Snapshot.LocationType locationType)
+ boolean quiescevm, Snapshot.LocationType locationType, boolean asyncBackup)
throws ResourceAllocationException {
VolumeInfo volume = volFactory.getVolume(volumeId);
@@ -2141,7 +2164,7 @@ private Snapshot orchestrateTakeVolumeSnapshot(Long volumeId, Long policyId, Lon
payload.setAccount(account);
payload.setQuiescevm(quiescevm);
payload.setLocationType(locationType);
-
+ payload.setAsyncBackup(asyncBackup);
volume.addPayload(payload);
return volService.takeSnapshot(volume);
@@ -2956,7 +2979,7 @@ protected Snapshot retrieve() {
}
public Outcome<Snapshot> takeVolumeSnapshotThroughJobQueue(final Long vmId, final Long volumeId,
- final Long policyId, final Long snapshotId, final Long accountId, final boolean quiesceVm, final Snapshot.LocationType locationType) {
+ final Long policyId, final Long snapshotId, final Long accountId, final boolean quiesceVm, final Snapshot.LocationType locationType, final boolean asyncBackup) {
final CallContext context = CallContext.current();
final User callingUser = context.getCallingUser();
@@ -2979,7 +3002,7 @@ protected Snapshot retrieve() {
// save work context info (there are some duplications)
VmWorkTakeVolumeSnapshot workInfo = new VmWorkTakeVolumeSnapshot(
callingUser.getId(), accountId != null ? accountId : callingAccount.getId(), vm.getId(),
- VolumeApiServiceImpl.VM_WORK_JOB_HANDLER, volumeId, policyId, snapshotId, quiesceVm, locationType);
+ VolumeApiServiceImpl.VM_WORK_JOB_HANDLER, volumeId, policyId, snapshotId, quiesceVm, locationType, asyncBackup);
workJob.setCmdInfo(VmWorkSerializer.serialize(workInfo));
_jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
@@ -3029,7 +3052,7 @@ protected Snapshot retrieve() {
private Pair<JobInfo.Status, String> orchestrateTakeVolumeSnapshot(VmWorkTakeVolumeSnapshot work) throws Exception {
Account account = _accountDao.findById(work.getAccountId());
orchestrateTakeVolumeSnapshot(work.getVolumeId(), work.getPolicyId(), work.getSnapshotId(),
- account, work.isQuiesceVm(), work.getLocationType());
+ account, work.isQuiesceVm(), work.getLocationType(), work.isAsyncBackup());
return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED,
_jobMgr.marshallResultObject(work.getSnapshotId()));
}
@@ -3057,4 +3080,5 @@ private VmWorkJobVO createPlaceHolderWork(long instanceId) {
return workJob;
}
+
}
diff --git a/server/src/com/cloud/storage/listener/SnapshotStateListener.java b/server/src/com/cloud/storage/listener/SnapshotStateListener.java
index f4decf6f058..344f81ca15f 100644
--- a/server/src/com/cloud/storage/listener/SnapshotStateListener.java
+++ b/server/src/com/cloud/storage/listener/SnapshotStateListener.java
@@ -101,7 +101,7 @@ private void pubishOnEventBus(String event, String status, Snapshot vo, State ol
eventDescription.put("old-state", oldState.name());
eventDescription.put("new-state", newState.name());
- String eventDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
+ String eventDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z").format(new Date());
eventDescription.put("eventDateTime", eventDate);
eventMsg.setDescription(eventDescription);
diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManager.java b/server/src/com/cloud/storage/snapshot/SnapshotManager.java
index 606109fe25b..c27c6992dcb 100644
--- a/server/src/com/cloud/storage/snapshot/SnapshotManager.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotManager.java
@@ -18,6 +18,8 @@
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.Configurable;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
@@ -25,13 +27,17 @@
import com.cloud.storage.Snapshot;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Volume;
-import org.apache.cloudstack.framework.config.ConfigKey;
/**
*
*
*/
-public interface SnapshotManager {
+public interface SnapshotManager extends Configurable {
+
+ public static final int HOURLYMAX = 8;
+ public static final int DAILYMAX = 8;
+ public static final int WEEKLYMAX = 8;
+ public static final int MONTHLYMAX = 12;
public static final int DELTAMAX = 16;
static final ConfigKey<Integer> SnapshotHourlyMax = new ConfigKey<Integer>(Integer.class, "snapshot.max.hourly", "Snapshots", "8",
@@ -44,6 +50,12 @@
"Maximum recurring monthly snapshots to be retained for a volume. If the limit is reached, snapshots from the beginning of the month are deleted so that newer ones can be saved. This limit does not apply to manual snapshots. If set to 0, recurring monthly snapshots can not be scheduled.", false, ConfigKey.Scope.Global, null);
static final ConfigKey<Boolean> usageSnapshotSelection = new ConfigKey<Boolean>("Usage", Boolean.class, "usage.snapshot.virtualsize.select", "false",
"Set the value to true if snapshot usage need to consider virtual size, else physical size is considered ", false);
+ public static final ConfigKey<Integer> BackupRetryAttempts = new ConfigKey<Integer>(Integer.class, "backup.retry", "Advanced", "3",
+ "Number of times to retry in creating backup of snapshot on secondary", false, ConfigKey.Scope.Global, null);
+
+ public static final ConfigKey<Integer> BackupRetryInterval = new ConfigKey<Integer>(Integer.class, "backup.retry.interval", "Advanced", "300",
+ "Time in seconds between retries in backing up snapshot to secondary", false, ConfigKey.Scope.Global, null);
+
void deletePoliciesForVolume(Long volumeId);
/**
diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
index b2caa818a46..f074c332e3c 100755
--- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
@@ -76,6 +76,7 @@
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.Ternary;
+import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.JoinBuilder;
@@ -114,6 +115,7 @@
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
@@ -128,6 +130,9 @@
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
@Component
public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implements SnapshotManager, SnapshotApiService, Configurable {
@@ -189,6 +194,19 @@
private int _totalRetries;
private int _pauseInterval;
+ private int snapshotBackupRetries, snapshotBackupRetryInterval;
+
+ private ScheduledExecutorService backupSnapshotExecutor;
+
+ @Override
+ public String getConfigComponentName() {
+ return SnapshotManager.class.getSimpleName();
+ }
+
+ @Override
+ public ConfigKey<?>[] getConfigKeys() {
+ return new ConfigKey<?>[] {BackupRetryAttempts, BackupRetryInterval, SnapshotHourlyMax, SnapshotDailyMax, SnapshotMonthlyMax, SnapshotWeeklyMax, usageSnapshotSelection};
+ }
@Override
public Answer sendToPool(Volume vol, Command cmd) {
@@ -1093,7 +1111,15 @@ public SnapshotInfo takeSnapshot(VolumeInfo volume) throws ResourceAllocationExc
throw new CloudRuntimeException("Can't find snapshot strategy to deal with snapshot:" + snapshotId);
}
- snapshotStrategy.takeSnapshot(snapshot);
+ SnapshotInfo snapshotOnPrimary = snapshotStrategy.takeSnapshot(snapshot);
+ if (payload.getAsyncBackup()) {
+ backupSnapshotExecutor.schedule(new BackupSnapshotTask(snapshotOnPrimary, snapshotBackupRetries - 1, snapshotStrategy), 0, TimeUnit.SECONDS);
+ } else {
+ SnapshotInfo backupedSnapshot = snapshotStrategy.backupSnapshot(snapshotOnPrimary);
+ if (backupedSnapshot != null) {
+ snapshotStrategy.postSnapshotCreation(snapshotOnPrimary);
+ }
+ }
try {
postCreateSnapshot(volume.getId(), snapshotId, payload.getSnapshotPolicyId());
@@ -1134,6 +1160,39 @@ public SnapshotInfo takeSnapshot(VolumeInfo volume) throws ResourceAllocationExc
return snapshot;
}
+ protected class BackupSnapshotTask extends ManagedContextRunnable {
+ SnapshotInfo snapshot;
+ int attempts;
+ SnapshotStrategy snapshotStrategy;
+
+ public BackupSnapshotTask(SnapshotInfo snap, int maxRetries, SnapshotStrategy strategy) {
+ snapshot = snap;
+ attempts = maxRetries;
+ snapshotStrategy = strategy;
+ }
+
+ @Override
+ protected void runInContext() {
+ try {
+ s_logger.debug("Value of attempts is " + (snapshotBackupRetries-attempts));
+
+ SnapshotInfo backupedSnapshot = snapshotStrategy.backupSnapshot(snapshot);
+
+ if (backupedSnapshot != null) {
+ snapshotStrategy.postSnapshotCreation(snapshot);
+ }
+ } catch (final Exception e) {
+ if (attempts >= 0) {
+ s_logger.debug("Backing up of snapshot failed, for snapshot with ID "+snapshot.getSnapshotId()+", left with "+attempts+" more attempts");
+ backupSnapshotExecutor.schedule(new BackupSnapshotTask(snapshot, --attempts, snapshotStrategy), snapshotBackupRetryInterval, TimeUnit.SECONDS);
+ } else {
+ s_logger.debug("Done with "+snapshotBackupRetries+" attempts in backing up of snapshot with ID "+snapshot.getSnapshotId());
+ snapshotSrv.cleanupOnSnapshotBackupFailure(snapshot);
+ }
+ }
+ }
+ }
+
private void updateSnapshotPayload(long storagePoolId, CreateSnapshotPayload payload) {
StoragePoolVO storagePoolVO = _storagePoolDao.findById(storagePoolId);
@@ -1185,6 +1244,9 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
_totalRetries = NumbersUtil.parseInt(_configDao.getValue("total.retries"), 4);
_pauseInterval = 2 * NumbersUtil.parseInt(_configDao.getValue("ping.interval"), 60);
+ snapshotBackupRetries = BackupRetryAttempts.value();
+ snapshotBackupRetryInterval = BackupRetryInterval.value();
+ backupSnapshotExecutor = Executors.newScheduledThreadPool(10, new NamedThreadFactory("BackupSnapshotTask"));
s_logger.info("Snapshot Manager is configured.");
return true;
@@ -1208,6 +1270,7 @@ public boolean start() {
@Override
public boolean stop() {
+ backupSnapshotExecutor.shutdown();
return true;
}
@@ -1330,14 +1393,4 @@ public Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName,
_resourceLimitMgr.incrementResourceCount(volume.getAccountId(), ResourceType.secondary_storage, new Long(volume.getSize()));
return snapshot;
}
-
-
- @Override
- public String getConfigComponentName() {
- return SnapshotManager.class.getSimpleName();
- }
-
- @Override
- public ConfigKey<?>[] getConfigKeys() {
- return new ConfigKey<?>[] { SnapshotHourlyMax, SnapshotDailyMax, SnapshotMonthlyMax, SnapshotWeeklyMax, usageSnapshotSelection}; }
}
diff --git a/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java
index f6c137916fe..7af1c190c93 100644
--- a/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java
@@ -22,6 +22,7 @@
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
+import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
@@ -64,6 +65,9 @@
import com.cloud.utils.db.GlobalLock;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.TransactionLegacy;
+import com.cloud.vm.snapshot.VMSnapshotManager;
+import com.cloud.vm.snapshot.VMSnapshotVO;
+import com.cloud.vm.snapshot.dao.VMSnapshotDao;
@Component
public class SnapshotSchedulerImpl extends ManagerBase implements SnapshotScheduler {
@@ -87,6 +91,12 @@
protected ApiDispatcher _dispatcher;
@Inject
protected AccountDao _acctDao;
+ @Inject
+ protected SnapshotApiService _snapshotService;
+ @Inject
+ protected VMSnapshotDao _vmSnapshotDao;
+ @Inject
+ protected VMSnapshotManager _vmSnaphostManager;
protected AsyncJobDispatcher _asyncDispatcher;
@@ -153,6 +163,13 @@ public void poll(final Date currentTimestamp) {
} finally {
scanLock.releaseRef();
}
+
+ try {
+ deleteExpiredVMSnapshots();
+ }
+ catch (Exception e) {
+ s_logger.warn("Error in expiring vm snapshots", e);
+ }
}
private void checkStatusOfCurrentlyExecutingSnapshots() {
@@ -219,6 +236,27 @@ private void checkStatusOfCurrentlyExecutingSnapshots() {
}
}
+ @DB
+ protected void deleteExpiredVMSnapshots() {
+ Date now = new Date();
+ List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.listAll();
+ for (VMSnapshotVO vmSnapshot : vmSnapshots) {
+ long accountId = vmSnapshot.getAccountId();
+ int expiration_interval_hours = VMSnapshotManager.VMSnapshotExpireInterval.valueIn(accountId);
+ if (expiration_interval_hours < 0 ) {
+ continue;
+ }
+ Date creationTime = vmSnapshot.getCreated();
+ long diffInHours = TimeUnit.MILLISECONDS.toHours(now.getTime() - creationTime.getTime());
+ if (diffInHours >= expiration_interval_hours) {
+ if (s_logger.isDebugEnabled()){
+ s_logger.debug("Deleting expired VM snapshot id: " + vmSnapshot.getId());
+ }
+ _vmSnaphostManager.deleteVMSnapshot(vmSnapshot.getId());
+ }
+ }
+ }
+
@DB
protected void scheduleSnapshots() {
String displayTime = DateUtil.displayDateInTimezone(DateUtil.GMT_TIMEZONE, _currentTimestamp);
diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java
index 1b7eb53e59c..f6494c3b77e 100644
--- a/server/src/com/cloud/template/TemplateManagerImpl.java
+++ b/server/src/com/cloud/template/TemplateManagerImpl.java
@@ -542,7 +542,7 @@ private String extract(Account caller, Long templateId, String url, Long zoneId,
_tmpltSvr.syncTemplateToRegionStore(templateId, tmpltStore);
TemplateInfo templateObject = _tmplFactory.getTemplate(templateId, tmpltStore);
- String extractUrl = tmpltStore.createEntityExtractUrl(tmpltStoreRef.getInstallPath(), template.getFormat(), templateObject);
+ String extractUrl = tmpltStore.createEntityExtractUrl(templateObject.getInstallPath(), template.getFormat(), templateObject);
tmpltStoreRef.setExtractUrl(extractUrl);
tmpltStoreRef.setExtractUrlCreated(DateUtil.now());
_tmplStoreDao.update(tmpltStoreRef.getId(), tmpltStoreRef);
@@ -673,9 +673,9 @@ public VMTemplateStoragePoolVO prepareTemplateForCreate(VMTemplateVO templ, Stor
}
@Override
- public String getChecksum(DataStore store, String templatePath) {
+ public String getChecksum(DataStore store, String templatePath, String algorithm) {
EndPoint ep = _epSelector.select(store);
- ComputeChecksumCommand cmd = new ComputeChecksumCommand(store.getTO(), templatePath);
+ ComputeChecksumCommand cmd = new ComputeChecksumCommand(store.getTO(), templatePath, algorithm);
Answer answer = null;
if (ep == null) {
String errMsg = "No remote endpoint to send command, check if host or ssvm is down?";
diff --git a/server/src/com/cloud/test/DatabaseConfig.java b/server/src/com/cloud/test/DatabaseConfig.java
index a27f6710631..7240374bfa7 100644
--- a/server/src/com/cloud/test/DatabaseConfig.java
+++ b/server/src/com/cloud/test/DatabaseConfig.java
@@ -18,9 +18,7 @@
import java.io.File;
import java.io.IOException;
-import java.math.BigInteger;
import java.net.URISyntaxException;
-import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Date;
import java.sql.PreparedStatement;
@@ -39,21 +37,12 @@
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
-import org.apache.log4j.Logger;
-import org.apache.log4j.xml.DOMConfigurator;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
import com.cloud.host.Status;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDaoImpl;
import com.cloud.storage.DiskOfferingVO;
-import com.cloud.storage.dao.DiskOfferingDaoImpl;
import com.cloud.storage.Storage.ProvisioningType;
+import com.cloud.storage.dao.DiskOfferingDaoImpl;
import com.cloud.utils.PropertiesUtil;
import com.cloud.utils.component.ComponentContext;
import com.cloud.utils.db.DB;
@@ -62,6 +51,15 @@
import com.cloud.utils.db.TransactionLegacy;
import com.cloud.utils.db.TransactionStatus;
import com.cloud.utils.net.NfsUtils;
+import org.apache.cloudstack.utils.security.DigestHelper;
+import org.apache.log4j.Logger;
+import org.apache.log4j.xml.DOMConfigurator;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
public class DatabaseConfig {
private static final Logger s_logger = Logger.getLogger(DatabaseConfig.class.getName());
@@ -1169,22 +1167,14 @@ protected void saveUser() {
printError("An email address for each user is required.");
}
- MessageDigest md5 = null;
+ String algorithm = "MD5";
+ String pwDigest;
try {
- md5 = MessageDigest.getInstance("MD5");
+ pwDigest = DigestHelper.getPaddedDigest(algorithm, password);
} catch (NoSuchAlgorithmException e) {
s_logger.error("error saving user", e);
return;
}
- md5.reset();
- BigInteger pwInt = new BigInteger(1, md5.digest(password.getBytes()));
- String pwStr = pwInt.toString(16);
- int padding = 32 - pwStr.length();
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < padding; i++) {
- sb.append('0'); // make sure the MD5 password is 32 digits long
- }
- sb.append(pwStr);
// create an account for the admin user first
final String insertAdminAccount = "INSERT INTO `cloud`.`account` (id, account_name, type, domain_id) VALUES (?, ?, '1', '1')";
@@ -1206,7 +1196,7 @@ protected void saveUser() {
PreparedStatement stmt = txn.prepareAutoCloseStatement(insertUser);
stmt.setLong(1, id);
stmt.setString(2, username);
- stmt.setString(3, sb.toString());
+ stmt.setString(3, pwDigest);
stmt.setString(4, firstname);
stmt.setString(5, lastname);
stmt.setString(6, email);
diff --git a/server/src/com/cloud/vm/UserVmManager.java b/server/src/com/cloud/vm/UserVmManager.java
index 411fd9b669f..51cce9d73a8 100644
--- a/server/src/com/cloud/vm/UserVmManager.java
+++ b/server/src/com/cloud/vm/UserVmManager.java
@@ -24,6 +24,7 @@
import org.apache.cloudstack.framework.config.ConfigKey;
import com.cloud.agent.api.VmDiskStatsEntry;
+import com.cloud.agent.api.VmNetworkStatsEntry;
import com.cloud.agent.api.VmStatsEntry;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
@@ -100,8 +101,6 @@ boolean upgradeVirtualMachine(Long id, Long serviceOfferingId, Map<String, Strin
boolean setupVmForPvlan(boolean add, Long hostId, NicProfile nic);
- void collectVmDiskStatistics(UserVmVO userVm);
-
UserVm updateVirtualMachine(long id, String displayName, String group, Boolean ha, Boolean isDisplayVmEnabled, Long osTypeId, String userData,
Boolean isDynamicallyScalable, HTTPMethod httpMethod, String customId, String hostName, String instanceName, List<Long> securityGroupIdList) throws ResourceUnavailableException, InsufficientCapacityException;
@@ -116,4 +115,6 @@ UserVm updateVirtualMachine(long id, String displayName, String group, Boolean h
void generateUsageEvent(VirtualMachine vm, boolean isDisplay, String eventType);
void persistDeviceBusInfo(UserVmVO paramUserVmVO, String paramString);
+
+ HashMap<Long, List<VmNetworkStatsEntry>> getVmNetworkStatistics(long hostId, String hostName, List<Long> vmIds);
}
diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java
old mode 100755
new mode 100644
index 3a47f381078..07dd0ea8466
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -99,6 +99,8 @@
import com.cloud.agent.api.GetVmDiskStatsAnswer;
import com.cloud.agent.api.GetVmDiskStatsCommand;
import com.cloud.agent.api.GetVmIpAddressCommand;
+import com.cloud.agent.api.GetVmNetworkStatsAnswer;
+import com.cloud.agent.api.GetVmNetworkStatsCommand;
import com.cloud.agent.api.GetVmStatsAnswer;
import com.cloud.agent.api.GetVmStatsCommand;
import com.cloud.agent.api.PvlanSetupCommand;
@@ -106,6 +108,7 @@
import com.cloud.agent.api.RestoreVMSnapshotCommand;
import com.cloud.agent.api.StartAnswer;
import com.cloud.agent.api.VmDiskStatsEntry;
+import com.cloud.agent.api.VmNetworkStatsEntry;
import com.cloud.agent.api.VmStatsEntry;
import com.cloud.agent.api.to.DiskTO;
import com.cloud.agent.api.to.NicTO;
@@ -128,6 +131,9 @@
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.DedicatedResourceDao;
import com.cloud.dc.dao.HostPodDao;
+import com.cloud.dc.dao.VlanDao;
+import com.cloud.dc.Vlan.VlanType;
+import com.cloud.dc.VlanVO;
import com.cloud.deploy.DataCenterDeployment;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlanner;
@@ -221,6 +227,7 @@
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.TemplateType;
+import com.cloud.storage.Snapshot;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolStatus;
@@ -248,11 +255,13 @@
import com.cloud.user.SSHKeyPair;
import com.cloud.user.SSHKeyPairVO;
import com.cloud.user.User;
+import com.cloud.user.UserStatisticsVO;
import com.cloud.user.UserVO;
import com.cloud.user.VmDiskStatisticsVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.SSHKeyPairDao;
import com.cloud.user.dao.UserDao;
+import com.cloud.user.dao.UserStatisticsDao;
import com.cloud.user.dao.VmDiskStatisticsDao;
import com.cloud.uservm.UserVm;
import com.cloud.utils.DateUtil;
@@ -289,6 +298,7 @@
import com.cloud.vm.snapshot.VMSnapshotManager;
import com.cloud.vm.snapshot.VMSnapshotVO;
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
+import com.cloud.storage.snapshot.SnapshotApiService;
public class UserVmManagerImpl extends ManagerBase implements UserVmManager, VirtualMachineGuru, UserVmService, Configurable {
private static final Logger s_logger = Logger.getLogger(UserVmManagerImpl.class);
@@ -454,6 +464,10 @@
@Inject
private ServiceOfferingDetailsDao serviceOfferingDetailsDao;
@Inject
+ private UserStatisticsDao _userStatsDao;
+ @Inject
+ private VlanDao _vlanDao;
+ @Inject
VolumeService _volService;
@Inject
VolumeDataFactory volFactory;
@@ -475,6 +489,8 @@
protected VMNetworkMapDao _vmNetworkMapDao;
@Inject
protected IpAddressManager _ipAddrMgr;
+ @Inject
+ private SnapshotApiService _snapshotService;
protected ScheduledExecutorService _executor = null;
protected ScheduledExecutorService _vmIpFetchExecutor = null;
@@ -902,6 +918,7 @@ private UserVm rebootVirtualMachine(long userId, long vmId) throws InsufficientC
if (vm.getState() == State.Running && vm.getHostId() != null) {
collectVmDiskStatistics(vm);
+ collectVmNetworkStatistics(vm);
DataCenterVO dc = _dcDao.findById(vm.getDataCenterId());
try {
if (dc.getNetworkType() == DataCenter.NetworkType.Advanced) {
@@ -1120,6 +1137,7 @@ public UserVm addNicToVirtualMachine(AddNicToVMCmd cmd) throws InvalidParameterV
Long vmId = cmd.getVmId();
Long networkId = cmd.getNetworkId();
String ipAddress = cmd.getIpAddress();
+ String macAddress = cmd.getMacAddress();
Account caller = CallContext.current().getCallingAccount();
UserVmVO vmInstance = _vmDao.findById(vmId);
@@ -1150,12 +1168,15 @@ public UserVm addNicToVirtualMachine(AddNicToVMCmd cmd) throws InvalidParameterV
throw new CloudRuntimeException("A NIC already exists for VM:" + vmInstance.getInstanceName() + " in network: " + network.getUuid());
}
- NicProfile profile = new NicProfile(null, null);
+ if(_nicDao.findByNetworkIdAndMacAddress(networkId, macAddress) != null) {
+ throw new CloudRuntimeException("A NIC with this MAC address exists for network: " + network.getUuid());
+ }
+
+ NicProfile profile = new NicProfile(ipAddress, null, macAddress);
if (ipAddress != null) {
if (!(NetUtils.isValidIp(ipAddress) || NetUtils.isValidIpv6(ipAddress))) {
throw new InvalidParameterValueException("Invalid format for IP address parameter: " + ipAddress);
}
- profile = new NicProfile(ipAddress, null);
}
// Perform permission check on VM
@@ -2616,6 +2637,8 @@ public UserVm rebootVirtualMachine(RebootVMCmd cmd) throws InsufficientCapacityE
_accountMgr.checkAccess(caller, null, true, vmInstance);
+ checkIfHostOfVMIsInPrepareForMaintenanceState(vmInstance.getHostId(), vmId, "Reboot");
+
// If the VM is Volatile in nature, on reboot discard the VM's root disk and create a new root disk for it: by calling restoreVM
long serviceOfferingId = vmInstance.getServiceOfferingId();
ServiceOfferingVO offering = _serviceOfferingDao.findById(vmInstance.getId(), serviceOfferingId);
@@ -2655,10 +2678,22 @@ public UserVm destroyVm(DestroyVMCmd cmd) throws ResourceUnavailableException, C
if (expunge && !_accountMgr.isAdmin(ctx.getCallingAccount().getId()) && !AllowUserExpungeRecoverVm.valueIn(cmd.getEntityOwnerId())) {
throw new PermissionDeniedException("Parameter " + ApiConstants.EXPUNGE + " can be passed by Admin only. Or when the allow.user.expunge.recover.vm key is set.");
}
+ // check if VM exists
+ UserVmVO vm = _vmDao.findById(vmId);
+
+ if (vm == null) {
+ throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
+ }
+
+ // check if there are active volume snapshots tasks
+ s_logger.debug("Checking if there are any ongoing snapshots on the ROOT volumes associated with VM with ID " + vmId);
+ if (checkStatusOfVolumeSnapshots(vmId, Volume.Type.ROOT)) {
+ throw new CloudRuntimeException("There is/are unbacked up snapshot(s) on ROOT volume, vm destroy is not permitted, please try again later.");
+ }
+ s_logger.debug("Found no ongoing snapshots on volume of type ROOT, for the vm with id " + vmId);
UserVm destroyedVm = destroyVm(vmId, expunge);
if (expunge) {
- UserVmVO vm = _vmDao.findById(vmId);
if (!expunge(vm, ctx.getCallingUserId(), ctx.getCallingAccount())) {
throw new CloudRuntimeException("Failed to expunge vm " + destroyedVm);
}
@@ -3068,7 +3103,7 @@ public UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serv
}
s_logger.debug("Creating network for account " + owner + " from the network offering id=" + requiredOfferings.get(0).getId() + " as a part of deployVM process");
Network newNetwork = _networkMgr.createGuestNetwork(requiredOfferings.get(0).getId(), owner.getAccountName() + "-network", owner.getAccountName() + "-network",
- null, null, null, null, owner, null, physicalNetwork, zone.getId(), ACLType.Account, null, null, null, null, true, null);
+ null, null, null, false, null, owner, null, physicalNetwork, zone.getId(), ACLType.Account, null, null, null, null, true, null);
if (newNetwork != null) {
defaultNetwork = _networkDao.findById(newNetwork.getId());
}
@@ -3347,17 +3382,19 @@ protected UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOf
if (requestedIpPair == null) {
requestedIpPair = new IpAddresses(null, null);
} else {
- _networkModel.checkRequestedIpAddresses(network.getId(), requestedIpPair.getIp4Address(), requestedIpPair.getIp6Address());
+ _networkModel.checkRequestedIpAddresses(network.getId(), requestedIpPair);
}
- NicProfile profile = new NicProfile(requestedIpPair.getIp4Address(), requestedIpPair.getIp6Address());
+ NicProfile profile = new NicProfile(requestedIpPair.getIp4Address(), requestedIpPair.getIp6Address(), requestedIpPair.getMacAddress());
if (defaultNetworkNumber == 0) {
defaultNetworkNumber++;
// if user requested specific ip for default network, add it
if (defaultIps.getIp4Address() != null || defaultIps.getIp6Address() != null) {
- _networkModel.checkRequestedIpAddresses(network.getId(), defaultIps.getIp4Address(), defaultIps.getIp6Address());
+ _networkModel.checkRequestedIpAddresses(network.getId(), defaultIps);
profile = new NicProfile(defaultIps.getIp4Address(), defaultIps.getIp6Address());
+ } else if (defaultIps.getMacAddress() != null) {
+ profile = new NicProfile(null, null, defaultIps.getMacAddress());
}
profile.setDefaultNic(true);
@@ -3603,8 +3640,14 @@ public UserVmVO doInTransaction(TransactionStatus status) throws InsufficientCap
_vmDao.persist(vm);
for (String key : customParameters.keySet()) {
- //handle double byte strings.
- vm.setDetail(key, Integer.toString(Integer.parseInt(customParameters.get(key))));
+ if( key.equalsIgnoreCase(VmDetailConstants.CPU_NUMBER) ||
+ key.equalsIgnoreCase(VmDetailConstants.CPU_SPEED) ||
+ key.equalsIgnoreCase(VmDetailConstants.MEMORY)) {
+ // handle double byte strings.
+ vm.setDetail(key, Integer.toString(Integer.parseInt(customParameters.get(key))));
+ } else {
+ vm.setDetail(key, customParameters.get(key));
+ }
}
vm.setDetail("deployvm", "true");
_vmDao.saveDetails(vm);
@@ -3689,6 +3732,144 @@ public void generateUsageEvent(VirtualMachine vm, boolean isDisplay, String even
}
}
+ @Override
+ public HashMap<Long, List<VmNetworkStatsEntry>> getVmNetworkStatistics(long hostId, String hostName, List<Long> vmIds) {
+ HashMap<Long, List<VmNetworkStatsEntry>> vmNetworkStatsById = new HashMap<Long, List<VmNetworkStatsEntry>>();
+
+ if (vmIds.isEmpty()) {
+ return vmNetworkStatsById;
+ }
+
+ List<String> vmNames = new ArrayList<String>();
+
+ for (Long vmId : vmIds) {
+ UserVmVO vm = _vmDao.findById(vmId);
+ vmNames.add(vm.getInstanceName());
+ }
+
+ Answer answer = _agentMgr.easySend(hostId, new GetVmNetworkStatsCommand(vmNames, _hostDao.findById(hostId).getGuid(), hostName));
+ if (answer == null || !answer.getResult()) {
+ s_logger.warn("Unable to obtain VM network statistics.");
+ return null;
+ } else {
+ HashMap<String, List<VmNetworkStatsEntry>> vmNetworkStatsByName = ((GetVmNetworkStatsAnswer)answer).getVmNetworkStatsMap();
+
+ if (vmNetworkStatsByName == null) {
+ s_logger.warn("Unable to obtain VM network statistics.");
+ return null;
+ }
+
+ for (String vmName : vmNetworkStatsByName.keySet()) {
+ vmNetworkStatsById.put(vmIds.get(vmNames.indexOf(vmName)), vmNetworkStatsByName.get(vmName));
+ }
+ }
+
+ return vmNetworkStatsById;
+ }
+
+ @Override
+ public void collectVmNetworkStatistics (final UserVm userVm) {
+ if (!userVm.getHypervisorType().equals(HypervisorType.KVM))
+ return;
+ s_logger.debug("Collect vm network statistics from host before stopping Vm");
+ long hostId = userVm.getHostId();
+ List<String> vmNames = new ArrayList<String>();
+ vmNames.add(userVm.getInstanceName());
+ final HostVO host = _hostDao.findById(hostId);
+
+ GetVmNetworkStatsAnswer networkStatsAnswer = null;
+ try {
+ networkStatsAnswer = (GetVmNetworkStatsAnswer) _agentMgr.easySend(hostId, new GetVmNetworkStatsCommand(vmNames, host.getGuid(), host.getName()));
+ } catch (Exception e) {
+ s_logger.warn("Error while collecting network stats for vm: " + userVm.getHostName() + " from host: " + host.getName(), e);
+ return;
+ }
+ if (networkStatsAnswer != null) {
+ if (!networkStatsAnswer.getResult()) {
+ s_logger.warn("Error while collecting network stats vm: " + userVm.getHostName() + " from host: " + host.getName() + "; details: " + networkStatsAnswer.getDetails());
+ return;
+ }
+ try {
+ final GetVmNetworkStatsAnswer networkStatsAnswerFinal = networkStatsAnswer;
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ HashMap<String, List<VmNetworkStatsEntry>> vmNetworkStatsByName = networkStatsAnswerFinal.getVmNetworkStatsMap();
+ if (vmNetworkStatsByName == null)
+ return;
+ List<VmNetworkStatsEntry> vmNetworkStats = vmNetworkStatsByName.get(userVm.getInstanceName());
+ if (vmNetworkStats == null)
+ return;
+
+ for (VmNetworkStatsEntry vmNetworkStat:vmNetworkStats) {
+ SearchCriteria<NicVO> sc_nic = _nicDao.createSearchCriteria();
+ sc_nic.addAnd("macAddress", SearchCriteria.Op.EQ, vmNetworkStat.getMacAddress());
+ NicVO nic = _nicDao.search(sc_nic, null).get(0);
+ List<VlanVO> vlan = _vlanDao.listVlansByNetworkId(nic.getNetworkId());
+ if (vlan == null || vlan.size() == 0 || vlan.get(0).getVlanType() != VlanType.DirectAttached)
+ break; // only get network statistics for DirectAttached network (shared networks in Basic zone and Advanced zone with/without SG)
+ UserStatisticsVO previousvmNetworkStats = _userStatsDao.findBy(userVm.getAccountId(), userVm.getDataCenterId(), nic.getNetworkId(), nic.getIPv4Address(), userVm.getId(), "UserVm");
+ if (previousvmNetworkStats == null) {
+ previousvmNetworkStats = new UserStatisticsVO(userVm.getAccountId(), userVm.getDataCenterId(),nic.getIPv4Address(), userVm.getId(), "UserVm", nic.getNetworkId());
+ _userStatsDao.persist(previousvmNetworkStats);
+ }
+ UserStatisticsVO vmNetworkStat_lock = _userStatsDao.lock(userVm.getAccountId(), userVm.getDataCenterId(), nic.getNetworkId(), nic.getIPv4Address(), userVm.getId(), "UserVm");
+
+ if ((vmNetworkStat.getBytesSent() == 0) && (vmNetworkStat.getBytesReceived() == 0)) {
+ s_logger.debug("bytes sent and received are all 0. Not updating user_statistics");
+ continue;
+ }
+
+ if (vmNetworkStat_lock == null) {
+ s_logger.warn("unable to find vm network stats from host for account: " + userVm.getAccountId() + " with vmId: " + userVm.getId()+ " and nicId:" + nic.getId());
+ continue;
+ }
+
+ if (previousvmNetworkStats != null
+ && ((previousvmNetworkStats.getCurrentBytesSent() != vmNetworkStat_lock.getCurrentBytesSent())
+ || (previousvmNetworkStats.getCurrentBytesReceived() != vmNetworkStat_lock.getCurrentBytesReceived()))) {
+ s_logger.debug("vm network stats changed from the time GetNmNetworkStatsCommand was sent. " +
+ "Ignoring current answer. Host: " + host.getName() + " . VM: " + vmNetworkStat.getVmName() +
+ " Sent(Bytes): " + vmNetworkStat.getBytesSent() + " Received(Bytes): " + vmNetworkStat.getBytesReceived());
+ continue;
+ }
+
+ if (vmNetworkStat_lock.getCurrentBytesSent() > vmNetworkStat.getBytesSent()) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Sent # of bytes that's less than the last one. " +
+ "Assuming something went wrong and persisting it. Host: " + host.getName() + " . VM: " + vmNetworkStat.getVmName() +
+ " Reported: " + vmNetworkStat.getBytesSent() + " Stored: " + vmNetworkStat_lock.getCurrentBytesSent());
+ }
+ vmNetworkStat_lock.setNetBytesSent(vmNetworkStat_lock.getNetBytesSent() + vmNetworkStat_lock.getCurrentBytesSent());
+ }
+ vmNetworkStat_lock.setCurrentBytesSent(vmNetworkStat.getBytesSent());
+
+ if (vmNetworkStat_lock.getCurrentBytesReceived() > vmNetworkStat.getBytesReceived()) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Received # of bytes that's less than the last one. " +
+ "Assuming something went wrong and persisting it. Host: " + host.getName() + " . VM: " + vmNetworkStat.getVmName() +
+ " Reported: " + vmNetworkStat.getBytesReceived() + " Stored: " + vmNetworkStat_lock.getCurrentBytesReceived());
+ }
+ vmNetworkStat_lock.setNetBytesReceived(vmNetworkStat_lock.getNetBytesReceived() + vmNetworkStat_lock.getCurrentBytesReceived());
+ }
+ vmNetworkStat_lock.setCurrentBytesReceived(vmNetworkStat.getBytesReceived());
+
+ if (! _dailyOrHourly) {
+ //update agg bytes
+ vmNetworkStat_lock.setAggBytesReceived(vmNetworkStat_lock.getNetBytesReceived() + vmNetworkStat_lock.getCurrentBytesReceived());
+ vmNetworkStat_lock.setAggBytesSent(vmNetworkStat_lock.getNetBytesSent() + vmNetworkStat_lock.getCurrentBytesSent());
+ }
+
+ _userStatsDao.update(vmNetworkStat_lock.getId(), vmNetworkStat_lock);
+ }
+ }
+ });
+ } catch (Exception e) {
+ s_logger.warn("Unable to update vm network statistics for vm: " + userVm.getId() + " from host: " + hostId, e);
+ }
+ }
+ }
+
private void validateUserData(String userData, HTTPMethod httpmethod) {
byte[] decodedUserData = null;
if (userData != null) {
@@ -4232,7 +4413,7 @@ public UserVm destroyVm(long vmId, boolean expunge) throws ResourceUnavailableEx
}
@Override
- public void collectVmDiskStatistics(final UserVmVO userVm) {
+ public void collectVmDiskStatistics(final UserVm userVm) {
// support KVM only util 2013.06.25
if (!userVm.getHypervisorType().equals(HypervisorType.KVM))
return;
@@ -4433,7 +4614,7 @@ public UserVm createVirtualMachine(DeployVMCmd cmd) throws InsufficientCapacityE
if(!serviceOffering.isDynamic()) {
for(String detail: cmd.getDetails().keySet()) {
- if(detail.equalsIgnoreCase("cpuNumber") || detail.equalsIgnoreCase("cpuSpeed") || detail.equalsIgnoreCase("memory")) {
+ if(detail.equalsIgnoreCase(VmDetailConstants.CPU_NUMBER) || detail.equalsIgnoreCase(VmDetailConstants.CPU_SPEED) || detail.equalsIgnoreCase(VmDetailConstants.MEMORY)) {
throw new InvalidParameterValueException("cpuNumber or cpuSpeed or memory should not be specified for static service offering");
}
}
@@ -4465,10 +4646,11 @@ public UserVm createVirtualMachine(DeployVMCmd cmd) throws InsufficientCapacityE
String ipAddress = cmd.getIpAddress();
String ip6Address = cmd.getIp6Address();
+ String macAddress = cmd.getMacAddress();
String name = cmd.getName();
String displayName = cmd.getDisplayName();
UserVm vm = null;
- IpAddresses addrs = new IpAddresses(ipAddress, ip6Address);
+ IpAddresses addrs = new IpAddresses(ipAddress, ip6Address, macAddress);
Long size = cmd.getSize();
String group = cmd.getGroup();
String userData = cmd.getUserData();
@@ -4678,6 +4860,8 @@ public VirtualMachine migrateVirtualMachine(Long vmId, Host destinationHost) thr
throw ex;
}
+ checkIfHostOfVMIsInPrepareForMaintenanceState(vm.getHostId(), vmId, "Migrate");
+
if(serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.pciDevice.toString()) != null) {
throw new InvalidParameterValueException("Live Migration of GPU enabled VM is not supported");
}
@@ -4744,10 +4928,17 @@ public VirtualMachine migrateVirtualMachine(Long vmId, Host destinationHost) thr
throw new VirtualMachineMigrationException("Destination host, hostId: " + destinationHost.getId()
+ " already has max Running VMs(count includes system VMs), cannot migrate to this host");
}
+ //check if there are any ongoing volume snapshots on the volumes associated with the VM.
+ s_logger.debug("Checking if there are any ongoing snapshots volumes associated with VM with ID " + vmId);
+ if (checkStatusOfVolumeSnapshots(vmId, null)) {
+ throw new CloudRuntimeException("There is/are unbacked up snapshot(s) on volume(s) attached to this VM, VM Migration is not permitted, please try again later.");
+ }
+ s_logger.debug("Found no ongoing snapshots on volumes associated with the vm with id " + vmId);
UserVmVO uservm = _vmDao.findById(vmId);
if (uservm != null) {
collectVmDiskStatistics(uservm);
+ collectVmNetworkStatistics(uservm);
}
_itMgr.migrate(vm.getUuid(), srcHostId, dest);
VMInstanceVO vmInstance = _vmInstanceDao.findById(vmId);
@@ -4770,6 +4961,16 @@ private boolean checkIfHostIsDedicated(HostVO host) {
}
}
+ private void checkIfHostOfVMIsInPrepareForMaintenanceState(Long hostId, Long vmId, String operation) {
+ HostVO host = _hostDao.findById(hostId);
+ if (host.getResourceState() != ResourceState.PrepareForMaintenance) {
+ return;
+ }
+
+ s_logger.debug("Host is in PrepareForMaintenance state - " + operation + " VM operation on the VM id: " + vmId + " is not allowed");
+ throw new InvalidParameterValueException(operation + " VM operation on the VM id: " + vmId + " is not allowed as host is preparing for maintenance mode");
+ }
+
private Long accountOfDedicatedHost(HostVO host) {
long hostId = host.getId();
DedicatedResourceVO dedicatedHost = _dedicatedDao.findByHostId(hostId);
@@ -5234,7 +5435,12 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
//snapshots: mark these removed in db
List<SnapshotVO> snapshots = _snapshotDao.listByVolumeIdIncludingRemoved(volume.getId());
for (SnapshotVO snapshot : snapshots) {
- _snapshotDao.remove(snapshot.getId());
+ boolean result = _snapshotService.deleteSnapshot(snapshot.getId());
+ if (result) {
+ s_logger.info("Snapshot id: " + snapshot.getId() + " delete successfully ");
+ } else {
+ s_logger.error("Unable to delete Snapshot id: " + snapshot.getId());
+ }
}
}
@@ -5517,7 +5723,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
s_logger.debug("Creating network for account " + newAccount + " from the network offering id=" + requiredOfferings.get(0).getId()
+ " as a part of deployVM process");
Network newNetwork = _networkMgr.createGuestNetwork(requiredOfferings.get(0).getId(), newAccount.getAccountName() + "-network",
- newAccount.getAccountName() + "-network", null, null, null, null, newAccount, null, physicalNetwork, zone.getId(), ACLType.Account, null, null,
+ newAccount.getAccountName() + "-network", null, null, null, false, null, newAccount, null, physicalNetwork, zone.getId(), ACLType.Account, null, null,
null, null, true, null);
// if the network offering has persistent set to true, implement the network
if (requiredOfferings.get(0).getIsPersistent()) {
@@ -5593,6 +5799,12 @@ public UserVm restoreVM(RestoreVMCmd cmd) throws InsufficientCapacityException,
_accountMgr.checkAccess(caller, null, true, vm);
+ //check if there are any active snapshots on volumes associated with the VM
+ s_logger.debug("Checking if there are any ongoing snapshots on the ROOT volumes associated with VM with ID " + vmId);
+ if (checkStatusOfVolumeSnapshots(vmId, Volume.Type.ROOT)) {
+ throw new CloudRuntimeException("There is/are unbacked up snapshot(s) on ROOT volume, Re-install VM is not permitted, please try again later.");
+ }
+ s_logger.debug("Found no ongoing snapshots on volume of type ROOT, for the vm with id " + vmId);
return restoreVMInternal(caller, vm, newTemplateId);
}
@@ -5871,8 +6083,10 @@ else if (host.getHypervisorType() == HypervisorType.VMware) {
@Override
public void prepareStop(VirtualMachineProfile profile) {
UserVmVO vm = _vmDao.findById(profile.getId());
- if (vm != null && vm.getState() == State.Stopping)
+ if (vm != null && vm.getState() == State.Stopping) {
collectVmDiskStatistics(vm);
+ collectVmNetworkStatistics(vm);
+ }
}
private void encryptAndStorePassword(UserVmVO vm, String password) {
@@ -5935,4 +6149,28 @@ public boolean isDisplayResourceEnabled(Long vmId) {
return true; // no info then default to true
}
+
+ private boolean checkStatusOfVolumeSnapshots(long vmId, Volume.Type type) {
+ List<VolumeVO> listVolumes = null;
+ if (type == Volume.Type.ROOT) {
+ listVolumes = _volsDao.findByInstanceAndType(vmId, type);
+ } else if (type == Volume.Type.DATADISK) {
+ listVolumes = _volsDao.findByInstanceAndType(vmId, type);
+ } else {
+ listVolumes = _volsDao.findByInstance(vmId);
+ }
+ s_logger.debug("Found "+listVolumes.size()+" no. of volumes of type "+type+" for vm with VM ID "+vmId);
+ for (VolumeVO volume : listVolumes) {
+ Long volumeId = volume.getId();
+ s_logger.debug("Checking status of snapshots for Volume with Volume Id: "+volumeId);
+ List<SnapshotVO> ongoingSnapshots = _snapshotDao.listByStatus(volumeId, Snapshot.State.Creating, Snapshot.State.CreatedOnPrimary, Snapshot.State.BackingUp);
+ int ongoingSnapshotsCount = ongoingSnapshots.size();
+ s_logger.debug("The count of ongoing Snapshots for VM with ID "+vmId+" and disk type "+type+" is "+ongoingSnapshotsCount);
+ if (ongoingSnapshotsCount > 0) {
+ s_logger.debug("Found "+ongoingSnapshotsCount+" no. of snapshots, on volume of type "+type+", which snapshots are not yet backed up");
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
index e4ee4516393..a84db084f21 100644
--- a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
+++ b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
@@ -36,6 +36,7 @@
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.framework.jobs.AsyncJob;
import org.apache.cloudstack.framework.jobs.AsyncJobExecutionContext;
@@ -101,6 +102,7 @@
import com.cloud.vm.UserVmDetailVO;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
+import com.cloud.vm.VmDetailConstants;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.State;
@@ -118,7 +120,7 @@
import com.cloud.vm.snapshot.dao.VMSnapshotDetailsDao;
@Component
-public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase implements VMSnapshotManager, VMSnapshotService, VmWorkJobHandler {
+public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase implements VMSnapshotManager, VMSnapshotService, VmWorkJobHandler, Configurable {
private static final Logger s_logger = Logger.getLogger(VMSnapshotManagerImpl.class);
public static final String VM_WORK_JOB_HANDLER = VMSnapshotManagerImpl.class.getSimpleName();
@@ -412,7 +414,7 @@ protected void addSupportForCustomServiceOffering(long vmId, long serviceOfferin
List<UserVmDetailVO> vmDetails = _userVmDetailsDao.listDetails(vmId);
List<VMSnapshotDetailsVO> vmSnapshotDetails = new ArrayList<VMSnapshotDetailsVO>();
for (UserVmDetailVO detail : vmDetails) {
- if(detail.getName().equalsIgnoreCase("cpuNumber") || detail.getName().equalsIgnoreCase("cpuSpeed") || detail.getName().equalsIgnoreCase("memory")) {
+ if(detail.getName().equalsIgnoreCase(VmDetailConstants.CPU_NUMBER) || detail.getName().equalsIgnoreCase(VmDetailConstants.CPU_SPEED) || detail.getName().equalsIgnoreCase(VmDetailConstants.MEMORY)) {
vmSnapshotDetails.add(new VMSnapshotDetailsVO(vmSnapshotId, detail.getName(), detail.getValue(), detail.isDisplay()));
}
}
@@ -1297,4 +1299,14 @@ public boolean deleteVMSnapshotsFromDB(Long vmId) {
}
return true;
}
+
+ @Override
+ public String getConfigComponentName() {
+ return VMSnapshotManager.class.getSimpleName();
+ }
+
+ @Override
+ public ConfigKey<?>[] getConfigKeys() {
+ return new ConfigKey<?>[] {VMSnapshotExpireInterval};
+ }
}
diff --git a/server/src/org/apache/cloudstack/acl/RoleManagerImpl.java b/server/src/org/apache/cloudstack/acl/RoleManagerImpl.java
index 053ec582ab7..f615aacf675 100644
--- a/server/src/org/apache/cloudstack/acl/RoleManagerImpl.java
+++ b/server/src/org/apache/cloudstack/acl/RoleManagerImpl.java
@@ -203,6 +203,12 @@ public boolean updateRolePermission(final Role role, final List<RolePermission>
return role != null && newOrder != null && rolePermissionsDao.update(role, newOrder);
}
+ @Override
+ public boolean updateRolePermission(Role role, RolePermission rolePermission, RolePermission.Permission permission) {
+ checkCallerAccess();
+ return role != null && rolePermissionsDao.update(role, rolePermission, permission);
+ }
+
@Override
@ActionEvent(eventType = EventTypes.EVENT_ROLE_PERMISSION_DELETE, eventDescription = "deleting Role Permission")
public boolean deleteRolePermission(final RolePermission rolePermission) {
diff --git a/server/src/org/apache/cloudstack/annotation/AnnotationManagerImpl.java b/server/src/org/apache/cloudstack/annotation/AnnotationManagerImpl.java
new file mode 100644
index 00000000000..2b658d55e35
--- /dev/null
+++ b/server/src/org/apache/cloudstack/annotation/AnnotationManagerImpl.java
@@ -0,0 +1,149 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.annotation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import com.cloud.event.ActionEvent;
+import com.cloud.event.EventTypes;
+import com.cloud.utils.component.ManagerBase;
+import com.cloud.utils.component.PluggableService;
+import org.apache.cloudstack.annotation.dao.AnnotationDao;
+import org.apache.cloudstack.api.command.admin.annotation.AddAnnotationCmd;
+import org.apache.cloudstack.api.command.admin.annotation.ListAnnotationsCmd;
+import org.apache.cloudstack.api.command.admin.annotation.RemoveAnnotationCmd;
+import org.apache.cloudstack.api.response.AnnotationResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.log4j.Logger;
+
+/**
+ * @since 4.11
+ */
+public final class AnnotationManagerImpl extends ManagerBase implements AnnotationService, PluggableService {
+ public static final Logger LOGGER = Logger.getLogger(AnnotationManagerImpl.class);
+
+ @Inject
+ private AnnotationDao annotationDao;
+
+ @Override
+ public ListResponse<AnnotationResponse> searchForAnnotations(ListAnnotationsCmd cmd) {
+ List<AnnotationVO> annotations = getAnnotationsForApiCmd(cmd);
+ List<AnnotationResponse> annotationResponses = convertAnnotationsToResponses(annotations);
+ return createAnnotationsResponseList(annotationResponses);
+ }
+
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ANNOTATION_CREATE, eventDescription = "creating an annotation on an entity")
+ public AnnotationResponse addAnnotation(AddAnnotationCmd addAnnotationCmd) {
+ return addAnnotation(addAnnotationCmd.getAnnotation(), addAnnotationCmd.getEntityType(), addAnnotationCmd.getEntityUuid());
+ }
+
+ public AnnotationResponse addAnnotation(String text, EntityType type, String uuid) {
+ CallContext ctx = CallContext.current();
+ String userUuid = ctx.getCallingUserUuid();
+
+ AnnotationVO annotation = new AnnotationVO(text, type, uuid);
+ annotation.setUserUuid(userUuid);
+ annotation = annotationDao.persist(annotation);
+ return createAnnotationResponse(annotation);
+ }
+
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ANNOTATION_REMOVE, eventDescription = "removing an annotation on an entity")
+ public AnnotationResponse removeAnnotation(RemoveAnnotationCmd removeAnnotationCmd) {
+ String uuid = removeAnnotationCmd.getUuid();
+ if(LOGGER.isDebugEnabled()) {
+ LOGGER.debug("marking annotation removed: " + uuid);
+ }
+ AnnotationVO annotation = annotationDao.findByUuid(uuid);
+ annotationDao.remove(annotation.getId());
+ return createAnnotationResponse(annotation);
+ }
+
+ private List<AnnotationVO> getAnnotationsForApiCmd(ListAnnotationsCmd cmd) {
+ List<AnnotationVO> annotations;
+ if(cmd.getUuid() != null) {
+ annotations = new ArrayList<>();
+ String uuid = cmd.getUuid().toString();
+ if(LOGGER.isDebugEnabled()) {
+ LOGGER.debug("getting single annotation by uuid: " + uuid);
+ }
+
+ annotations.add(annotationDao.findByUuid(uuid));
+ } else if( ! (cmd.getEntityType() == null || cmd.getEntityType().isEmpty()) ) {
+ String type = cmd.getEntityType();
+ if(LOGGER.isDebugEnabled()) {
+ LOGGER.debug("getting annotations for type: " + type);
+ }
+ if (cmd.getEntityUuid() != null) {
+ String uuid = cmd.getEntityUuid().toString();
+ if(LOGGER.isDebugEnabled()) {
+ LOGGER.debug("getting annotations for entity: " + uuid);
+ }
+ annotations = annotationDao.findByEntity(type,cmd.getEntityUuid().toString());
+ } else {
+ annotations = annotationDao.findByEntityType(type);
+ }
+ } else {
+ if(LOGGER.isDebugEnabled()) {
+ LOGGER.debug("getting all annotations");
+ }
+ annotations = annotationDao.listAll();
+ }
+ return annotations;
+ }
+
+ private List<AnnotationResponse> convertAnnotationsToResponses(List<AnnotationVO> annotations) {
+ List<AnnotationResponse> annotationResponses = new ArrayList<>();
+ for (AnnotationVO annotation : annotations) {
+ annotationResponses.add(createAnnotationResponse(annotation));
+ }
+ return annotationResponses;
+ }
+
+ private ListResponse<AnnotationResponse> createAnnotationsResponseList(List<AnnotationResponse> annotationResponses) {
+ ListResponse<AnnotationResponse> listResponse = new ListResponse<>();
+ listResponse.setResponses(annotationResponses);
+ return listResponse;
+ }
+
+ public static AnnotationResponse createAnnotationResponse(AnnotationVO annotation) {
+ AnnotationResponse response = new AnnotationResponse();
+ response.setUuid(annotation.getUuid());
+ response.setEntityType(annotation.getEntityType());
+ response.setEntityUuid(annotation.getEntityUuid());
+ response.setAnnotation(annotation.getAnnotation());
+ response.setUserUuid(annotation.getUserUuid());
+ response.setCreated(annotation.getCreated());
+ response.setRemoved(annotation.getRemoved());
+ response.setObjectName("annotation");
+
+ return response;
+ }
+
+ @Override public List<Class<?>> getCommands() {
+ final List<Class<?>> cmdList = new ArrayList<>();
+ cmdList.add(AddAnnotationCmd.class);
+ cmdList.add(ListAnnotationsCmd.class);
+ cmdList.add(RemoveAnnotationCmd.class);
+ return cmdList;
+ }
+}
diff --git a/server/src/org/apache/cloudstack/ca/CAManagerImpl.java b/server/src/org/apache/cloudstack/ca/CAManagerImpl.java
new file mode 100644
index 00000000000..3a904315fe1
--- /dev/null
+++ b/server/src/org/apache/cloudstack/ca/CAManagerImpl.java
@@ -0,0 +1,440 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ca;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.command.admin.ca.IssueCertificateCmd;
+import org.apache.cloudstack.api.command.admin.ca.ListCAProvidersCmd;
+import org.apache.cloudstack.api.command.admin.ca.ListCaCertificateCmd;
+import org.apache.cloudstack.api.command.admin.ca.ProvisionCertificateCmd;
+import org.apache.cloudstack.api.command.admin.ca.RevokeCertificateCmd;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.framework.ca.CAProvider;
+import org.apache.cloudstack.framework.ca.Certificate;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.managed.context.ManagedContextRunnable;
+import org.apache.cloudstack.poll.BackgroundPollManager;
+import org.apache.cloudstack.poll.BackgroundPollTask;
+import org.apache.cloudstack.utils.identity.ManagementServerNode;
+import org.apache.cloudstack.utils.security.CertUtils;
+import org.apache.log4j.Logger;
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.alert.AlertManager;
+import com.cloud.certificate.CrlVO;
+import com.cloud.certificate.dao.CrlDao;
+import com.cloud.event.ActionEvent;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.AgentUnavailableException;
+import com.cloud.exception.OperationTimedoutException;
+import com.cloud.host.Host;
+import com.cloud.host.Status;
+import com.cloud.host.dao.HostDao;
+import com.cloud.utils.component.ManagerBase;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.google.common.base.Strings;
+
+public class CAManagerImpl extends ManagerBase implements CAManager {
+ public static final Logger LOG = Logger.getLogger(CAManagerImpl.class);
+
+ @Inject
+ private CrlDao crlDao;
+ @Inject
+ private HostDao hostDao;
+ @Inject
+ private AgentManager agentManager;
+ @Inject
+ private BackgroundPollManager backgroundPollManager;
+ @Inject
+ private AlertManager alertManager;
+
+ private static CAProvider configuredCaProvider;
+ private static Map<String, CAProvider> caProviderMap = new HashMap<>();
+ private static Map<String, Date> alertMap = new ConcurrentHashMap<>();
+ private static Map<String, X509Certificate> activeCertMap = new ConcurrentHashMap<>();
+
+ private List<CAProvider> caProviders;
+
+ private CAProvider getConfiguredCaProvider() {
+ if (configuredCaProvider != null) {
+ return configuredCaProvider;
+ }
+ if (caProviderMap.containsKey(CAProviderPlugin.value()) && caProviderMap.get(CAProviderPlugin.value()) != null) {
+ configuredCaProvider = caProviderMap.get(CAProviderPlugin.value());
+ return configuredCaProvider;
+ }
+ throw new CloudRuntimeException("Failed to find default configured CA provider plugin");
+ }
+
+ private CAProvider getCAProvider(final String provider) {
+ if (Strings.isNullOrEmpty(provider)) {
+ return getConfiguredCaProvider();
+ }
+ final String caProviderName = provider.toLowerCase();
+ if (!caProviderMap.containsKey(caProviderName)) {
+ throw new CloudRuntimeException(String.format("CA provider plugin '%s' not found", caProviderName));
+ }
+ final CAProvider caProvider = caProviderMap.get(caProviderName);
+ if (caProvider == null) {
+ throw new CloudRuntimeException(String.format("CA provider plugin '%s' returned is null", caProviderName));
+ }
+ return caProvider;
+ }
+
+ ///////////////////////////////////////////////////////////
+ /////////////// CA Manager API Handlers ///////////////////
+ ///////////////////////////////////////////////////////////
+
+ @Override
+ public List<CAProvider> getCaProviders() {
+ return caProviders;
+ }
+
+ @Override
+ public Map<String, X509Certificate> getActiveCertificatesMap() {
+ return activeCertMap;
+ }
+
+ @Override
+ public boolean canProvisionCertificates() {
+ return getConfiguredCaProvider().canProvisionCertificates();
+ }
+
+ @Override
+ public String getCaCertificate(final String caProvider) throws IOException {
+ final CAProvider provider = getCAProvider(caProvider);
+ return CertUtils.x509CertificatesToPem(provider.getCaCertificate());
+ }
+
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_CA_CERTIFICATE_ISSUE, eventDescription = "issuing certificate", async = true)
+ public Certificate issueCertificate(final String csr, final List<String> domainNames, final List<String> ipAddresses, final Integer validityDuration, final String caProvider) {
+ CallContext.current().setEventDetails("domain(s): " + domainNames + " addresses: " + ipAddresses);
+ final CAProvider provider = getCAProvider(caProvider);
+ Integer validity = CAManager.CertValidityPeriod.value();
+ if (validityDuration != null) {
+ validity = validityDuration;
+ }
+ if (Strings.isNullOrEmpty(csr)) {
+ if (domainNames == null || domainNames.isEmpty()) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "No domains or CSR provided");
+ }
+ return provider.issueCertificate(domainNames, ipAddresses, validity);
+ }
+ return provider.issueCertificate(csr, domainNames, ipAddresses, validity);
+ }
+
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_CA_CERTIFICATE_REVOKE, eventDescription = "revoking certificate", async = true)
+ public boolean revokeCertificate(final BigInteger certSerial, final String certCn, final String caProvider) {
+ CallContext.current().setEventDetails("cert serial: " + certSerial);
+ final CrlVO crl = crlDao.revokeCertificate(certSerial, certCn);
+ if (crl != null && crl.getCertSerial().equals(certSerial)) {
+ final CAProvider provider = getCAProvider(caProvider);
+ return provider.revokeCertificate(certSerial, certCn);
+ }
+ return false;
+ }
+
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_CA_CERTIFICATE_PROVISION, eventDescription = "provisioning certificate for host", async = true)
+ public boolean provisionCertificate(final Host host, final Boolean reconnect, final String caProvider) {
+ if (host == null) {
+ throw new CloudRuntimeException("Unable to find valid host to renew certificate for");
+ }
+ CallContext.current().setEventDetails("host id: " + host.getId());
+ CallContext.current().putContextParameter(Host.class, host.getUuid());
+ final String csr;
+ try {
+ csr = generateKeyStoreAndCsr(host, null);
+ if (Strings.isNullOrEmpty(csr)) {
+ return false;
+ }
+ final Certificate certificate = issueCertificate(csr, Collections.singletonList(host.getName()), Arrays.asList(host.getPrivateIpAddress(), host.getPublicIpAddress(), host.getStorageIpAddress()), CAManager.CertValidityPeriod.value(), caProvider);
+ return deployCertificate(host, certificate, reconnect, null);
+ } catch (final AgentUnavailableException | OperationTimedoutException e) {
+ LOG.error("Host/agent is not available or operation timed out, failed to setup keystore and generate CSR for host/agent id=" + host.getId() + ", due to: ", e);
+ throw new CloudRuntimeException("Failed to generate keystore and get CSR from the host/agent id=" + host.getId());
+ }
+ }
+
+ @Override
+ public String generateKeyStoreAndCsr(final Host host, final Map<String, String> sshAccessDetails) throws AgentUnavailableException, OperationTimedoutException {
+ final SetupKeyStoreCommand cmd = new SetupKeyStoreCommand(CertValidityPeriod.value());
+ if (sshAccessDetails != null && !sshAccessDetails.isEmpty()) {
+ cmd.setAccessDetail(sshAccessDetails);
+ }
+ CallContext.current().setEventDetails("generating keystore and CSR for host id: " + host.getId());
+ final SetupKeystoreAnswer answer = (SetupKeystoreAnswer) agentManager.send(host.getId(), cmd);
+ return answer.getCsr();
+ }
+
+ @Override
+ public boolean deployCertificate(final Host host, final Certificate certificate, final Boolean reconnect, final Map<String, String> sshAccessDetails) throws AgentUnavailableException, OperationTimedoutException {
+ final SetupCertificateCommand cmd = new SetupCertificateCommand(certificate);
+ if (sshAccessDetails != null && !sshAccessDetails.isEmpty()) {
+ cmd.setAccessDetail(sshAccessDetails);
+ }
+ CallContext.current().setEventDetails("deploying certificate for host id: " + host.getId());
+ final SetupCertificateAnswer answer = (SetupCertificateAnswer) agentManager.send(host.getId(), cmd);
+ if (answer.getResult()) {
+ CallContext.current().setEventDetails("successfully deployed certificate for host id: " + host.getId());
+ } else {
+ CallContext.current().setEventDetails("failed to deploy certificate for host id: " + host.getId());
+ }
+
+ if (answer.getResult()) {
+ getActiveCertificatesMap().put(host.getPrivateIpAddress(), certificate.getClientCertificate());
+ if (sshAccessDetails == null && reconnect != null && reconnect) {
+ LOG.info(String.format("Successfully setup certificate on host, reconnecting with agent with id=%d, name=%s, address=%s",
+ host.getId(), host.getName(), host.getPublicIpAddress()));
+ return agentManager.reconnect(host.getId());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void purgeHostCertificate(final Host host) {
+ if (host == null) {
+ return;
+ }
+ final String privateAddress = host.getPrivateIpAddress();
+ final String publicAddress = host.getPublicIpAddress();
+ final Map<String, X509Certificate> activeCertsMap = getActiveCertificatesMap();
+ if (!Strings.isNullOrEmpty(privateAddress) && activeCertsMap.containsKey(privateAddress)) {
+ activeCertsMap.remove(privateAddress);
+ }
+ if (!Strings.isNullOrEmpty(publicAddress) && activeCertsMap.containsKey(publicAddress)) {
+ activeCertsMap.remove(publicAddress);
+ }
+ }
+
+ @Override
+ public void sendAlert(final Host host, final String subject, final String message) {
+ if (host == null) {
+ return;
+ }
+ alertManager.sendAlert(AlertManager.AlertType.ALERT_TYPE_CA_CERT,
+ host.getDataCenterId(), host.getPodId(), subject, message);
+ }
+
+ @Override
+ public SSLEngine createSSLEngine(final SSLContext sslContext, final String remoteAddress) throws GeneralSecurityException, IOException {
+ if (sslContext == null) {
+ throw new CloudRuntimeException("SSLContext provided to create SSLEngine is null, aborting");
+ }
+ if (Strings.isNullOrEmpty(remoteAddress)) {
+ throw new CloudRuntimeException("Remote client address connecting to mgmt server cannot be empty/null");
+ }
+ return getConfiguredCaProvider().createSSLEngine(sslContext, remoteAddress, getActiveCertificatesMap());
+ }
+
+ @Override
+ public KeyStore getManagementKeyStore() throws KeyStoreException {
+ return getConfiguredCaProvider().getManagementKeyStore();
+ }
+
+ @Override
+ public char[] getKeyStorePassphrase() {
+ return getConfiguredCaProvider().getKeyStorePassphrase();
+ }
+
+ ////////////////////////////////////////////////////
+ /////////////// CA Manager Setup ///////////////////
+ ////////////////////////////////////////////////////
+
+ public static final class CABackgroundTask extends ManagedContextRunnable implements BackgroundPollTask {
+ private CAManager caManager;
+ private HostDao hostDao;
+
+ public CABackgroundTask(final CAManager caManager, final HostDao hostDao) {
+ this.caManager = caManager;
+ this.hostDao = hostDao;
+ }
+
+ @Override
+ protected void runInContext() {
+ try {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("CA background task is running...");
+ }
+ final DateTime now = DateTime.now(DateTimeZone.UTC);
+ final Map<String, X509Certificate> certsMap = caManager.getActiveCertificatesMap();
+ for (final Iterator<Map.Entry<String, X509Certificate>> it = certsMap.entrySet().iterator(); it.hasNext(); ) {
+ final Map.Entry<String, X509Certificate> entry = it.next();
+ if (entry == null) {
+ continue;
+ }
+ final String hostIp = entry.getKey();
+ final X509Certificate certificate = entry.getValue();
+ if (certificate == null) {
+ it.remove();
+ continue;
+ }
+ final Host host = hostDao.findByIp(hostIp);
+ if (host == null || host.getManagementServerId() == null ||
+ host.getManagementServerId() != ManagementServerNode.getManagementServerId() ||
+ host.getStatus() != Status.Up) {
+ if (host == null ||
+ (host.getManagementServerId() != null &&
+ host.getManagementServerId() != ManagementServerNode.getManagementServerId())) {
+ it.remove();
+ }
+ continue;
+ }
+
+ final String hostDescription = String.format("host id=%d, uuid=%s, name=%s, ip=%s, zone id=%d",
+ host.getId(), host.getUuid(), host.getName(), hostIp, host.getDataCenterId());
+
+ try {
+ certificate.checkValidity(now.plusDays(CertExpiryAlertPeriod.valueIn(host.getClusterId())).toDate());
+ } catch (final CertificateExpiredException | CertificateNotYetValidException e) {
+ LOG.warn("Certificate is going to expire for " + hostDescription);
+ if (AutomaticCertRenewal.valueIn(host.getClusterId())) {
+ try {
+ LOG.debug("Attempting certificate auto-renewal for " + hostDescription);
+ boolean result = caManager.provisionCertificate(host, false, null);
+ if (result) {
+ LOG.debug("Succeeded in auto-renewing certificate for " + hostDescription);
+ } else {
+ LOG.debug("Failed in auto-renewing certificate for " + hostDescription);
+ }
+ } catch (final Throwable ex) {
+ LOG.warn("Failed to auto-renew certificate for " + hostDescription + ", with error=", ex);
+ caManager.sendAlert(host, "Certificate auto-renewal failed for " + hostDescription,
+ String.format("Certificate is going to expire for %s. Auto-renewal failed to renew the certificate, please renew it manually. It is not valid after %s.", hostDescription, certificate.getNotAfter()));
+ }
+ } else {
+ if (alertMap.containsKey(hostIp)) {
+ final Date lastSentDate = alertMap.get(hostIp);
+ if (now.minusDays(1).toDate().before(lastSentDate)) {
+ continue;
+ }
+ }
+ caManager.sendAlert(host, "Certificate expiring soon for " + hostDescription,
+ String.format("Certificate is going to expire for %s. Please renew it, it is not valid after %s.",
+ hostDescription, certificate.getNotAfter()));
+ alertMap.put(hostIp, new Date());
+ }
+ }
+ }
+ } catch (final Throwable t) {
+ LOG.error("Error trying to run CA background task", t);
+ }
+ }
+
+ @Override
+ public Long getDelay() {
+ return CABackgroundJobDelay.value() * 1000L;
+ }
+ }
+
+ public void setCaProviders(final List<CAProvider> caProviders) {
+ this.caProviders = caProviders;
+ initializeCaProviderMap();
+ }
+
+ private void initializeCaProviderMap() {
+ if (caProviderMap != null && caProviderMap.size() != caProviders.size()) {
+ for (final CAProvider caProvider : caProviders) {
+ caProviderMap.put(caProvider.getProviderName().toLowerCase(), caProvider);
+ }
+ }
+ }
+
+ @Override
+ public boolean start() {
+ super.start();
+ initializeCaProviderMap();
+ if (caProviderMap.containsKey(CAProviderPlugin.value())) {
+ configuredCaProvider = caProviderMap.get(CAProviderPlugin.value());
+ }
+ if (configuredCaProvider == null) {
+ LOG.error("Failed to find valid configured CA provider, please check!");
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
+ backgroundPollManager.submitTask(new CABackgroundTask(this, hostDao));
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////
+ /////////////// CA Manager Descriptors ///////////////////
+ //////////////////////////////////////////////////////////
+
+ @Override
+ public List<Class<?>> getCommands() {
+ final List<Class<?>> cmdList = new ArrayList<Class<?>>();
+ cmdList.add(ListCAProvidersCmd.class);
+ cmdList.add(ListCaCertificateCmd.class);
+ cmdList.add(IssueCertificateCmd.class);
+ cmdList.add(ProvisionCertificateCmd.class);
+ cmdList.add(RevokeCertificateCmd.class);
+ return cmdList;
+ }
+
+ @Override
+ public String getConfigComponentName() {
+ return CAManager.class.getSimpleName();
+ }
+
+ @Override
+ public ConfigKey<?>[] getConfigKeys() {
+ return new ConfigKey<?>[]{
+ CAProviderPlugin,
+ CertKeySize,
+ CertSignatureAlgorithm,
+ CertValidityPeriod,
+ AutomaticCertRenewal,
+ CABackgroundJobDelay,
+ CertExpiryAlertPeriod
+ };
+ }
+}
diff --git a/server/src/org/apache/cloudstack/ha/HAManager.java b/server/src/org/apache/cloudstack/ha/HAManager.java
new file mode 100644
index 00000000000..3de7b49dd98
--- /dev/null
+++ b/server/src/org/apache/cloudstack/ha/HAManager.java
@@ -0,0 +1,77 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ha;
+
+import com.cloud.ha.Investigator;
+import com.cloud.host.Host;
+import com.cloud.host.Status;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.ha.provider.HAProvider;
+
+public interface HAManager extends HAConfigManager {
+
+ ConfigKey<Integer> MaxConcurrentHealthCheckOperations = new ConfigKey<>("Advanced", Integer.class,
+ "ha.max.concurrent.health.check.operations",
+ "50",
+ "The number of concurrent health check operations per management server. This setting determines the size of the thread pool consuming the HEALTH CHECK queue.", true);
+
+ ConfigKey<Integer> MaxPendingHealthCheckOperations = new ConfigKey<>("Advanced", Integer.class,
+ "ha.max.pending.health.check.operations",
+ "5000",
+ "The number of pending health check operations per management server. This setting determines the size of the HEALTH CHECK queue.", true);
+
+ ConfigKey<Integer> MaxConcurrentActivityCheckOperations = new ConfigKey<>("Advanced", Integer.class,
+ "ha.max.concurrent.activity.check.operations",
+ "25",
+ "The number of concurrent activity check operations per management server. This setting determines the size of the thread pool consuming the ACTIVITY CHECK queue.",
+ true);
+
+ ConfigKey<Integer> MaxPendingActivityCheckOperations = new ConfigKey<>("Advanced", Integer.class,
+ "ha.max.pending.activity.check.operations",
+ "2500",
+ "The number of pending activity check operations per management server. This setting determines the size of the size of the ACTIVITY CHECK queue.", true);
+
+ ConfigKey<Integer> MaxConcurrentRecoveryOperations = new ConfigKey<>("Advanced", Integer.class,
+ "ha.max.concurrent.recovery.operations",
+ "25",
+ "The number of concurrent recovery operations per management server.", true);
+
+ ConfigKey<Integer> MaxPendingRecoveryOperations = new ConfigKey<>("Advanced", Integer.class,
+ "ha.max.pending.recovery.operations",
+ "2500",
+ "The number of pending recovery operations per management server. This setting determines the size of the size of the RECOVERY queue.", true);
+
+ ConfigKey<Integer> MaxConcurrentFenceOperations = new ConfigKey<>("Advanced", Integer.class,
+ "ha.max.concurrent.fence.operations",
+ "25",
+ "The number of concurrent fence operations per management server.", true);
+
+ ConfigKey<Integer> MaxPendingFenceOperations = new ConfigKey<>("Advanced", Integer.class,
+ "ha.max.pending.fence.operations",
+ "2500",
+ "The number of pending fence operations per management server. This setting determines the size of the size of the FENCE queue.", true);
+
+ boolean transitionHAState(final HAConfig.Event event, final HAConfig haConfig);
+ HAProvider getHAProvider(final String name);
+ HAResourceCounter getHACounter(final Long resourceId, final HAResource.ResourceType resourceType);
+ void purgeHACounter(final Long resourceId, final HAResource.ResourceType resourceType);
+
+ boolean isHAEligible(final HAResource resource);
+ Boolean isVMAliveOnHost(final Host host) throws Investigator.UnknownVM;
+ Status getHostStatus(final Host host);
+}
\ No newline at end of file
diff --git a/server/src/org/apache/cloudstack/ha/HAManagerImpl.java b/server/src/org/apache/cloudstack/ha/HAManagerImpl.java
new file mode 100644
index 00000000000..49d9432fa15
--- /dev/null
+++ b/server/src/org/apache/cloudstack/ha/HAManagerImpl.java
@@ -0,0 +1,714 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ha;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.command.admin.ha.ConfigureHAForHostCmd;
+import org.apache.cloudstack.api.command.admin.ha.DisableHAForClusterCmd;
+import org.apache.cloudstack.api.command.admin.ha.DisableHAForHostCmd;
+import org.apache.cloudstack.api.command.admin.ha.DisableHAForZoneCmd;
+import org.apache.cloudstack.api.command.admin.ha.EnableHAForClusterCmd;
+import org.apache.cloudstack.api.command.admin.ha.EnableHAForHostCmd;
+import org.apache.cloudstack.api.command.admin.ha.EnableHAForZoneCmd;
+import org.apache.cloudstack.api.command.admin.ha.ListHostHAProvidersCmd;
+import org.apache.cloudstack.api.command.admin.ha.ListHostHAResourcesCmd;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.Configurable;
+import org.apache.cloudstack.ha.dao.HAConfigDao;
+import org.apache.cloudstack.ha.provider.HAProvider;
+import org.apache.cloudstack.ha.provider.HAProvider.HAProviderConfig;
+import org.apache.cloudstack.ha.task.ActivityCheckTask;
+import org.apache.cloudstack.ha.task.FenceTask;
+import org.apache.cloudstack.ha.task.HealthCheckTask;
+import org.apache.cloudstack.ha.task.RecoveryTask;
+import org.apache.cloudstack.kernel.Partition;
+import org.apache.cloudstack.managed.context.ManagedContextRunnable;
+import org.apache.cloudstack.poll.BackgroundPollManager;
+import org.apache.cloudstack.poll.BackgroundPollTask;
+import org.apache.cloudstack.utils.identity.ManagementServerNode;
+import org.apache.log4j.Logger;
+
+import com.cloud.cluster.ClusterManagerListener;
+import com.cloud.cluster.ManagementServerHost;
+import com.cloud.dc.ClusterDetailsDao;
+import com.cloud.dc.ClusterDetailsVO;
+import com.cloud.dc.DataCenter;
+import com.cloud.dc.DataCenterDetailVO;
+import com.cloud.dc.dao.DataCenterDetailsDao;
+import com.cloud.domain.Domain;
+import com.cloud.event.ActionEvent;
+import com.cloud.event.ActionEventUtils;
+import com.cloud.event.EventTypes;
+import com.cloud.ha.Investigator;
+import com.cloud.host.Host;
+import com.cloud.host.Status;
+import com.cloud.host.dao.HostDao;
+import com.cloud.org.Cluster;
+import com.cloud.utils.component.ComponentContext;
+import com.cloud.utils.component.ManagerBase;
+import com.cloud.utils.component.PluggableService;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.db.TransactionCallback;
+import com.cloud.utils.db.TransactionStatus;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.fsm.NoTransitionException;
+import com.cloud.utils.fsm.StateListener;
+import com.cloud.utils.fsm.StateMachine2;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+
+public final class HAManagerImpl extends ManagerBase implements HAManager, ClusterManagerListener, PluggableService, Configurable, StateListener<HAConfig.HAState, HAConfig.Event, HAConfig> {
+ public static final Logger LOG = Logger.getLogger(HAManagerImpl.class);
+
+ @Inject
+ private HAConfigDao haConfigDao;
+
+ @Inject
+ private HostDao hostDao;
+
+ @Inject
+ private ClusterDetailsDao clusterDetailsDao;
+
+ @Inject
+ private DataCenterDetailsDao dataCenterDetailsDao;
+
+ @Inject
+ private BackgroundPollManager pollManager;
+
+ private List<HAProvider<HAResource>> haProviders;
+ private Map<String, HAProvider<HAResource>> haProviderMap = new HashMap<>();
+
+ private static ExecutorService healthCheckExecutor;
+ private static ExecutorService activityCheckExecutor;
+ private static ExecutorService recoveryExecutor;
+ private static ExecutorService fenceExecutor;
+
+ private static final String HA_ENABLED_DETAIL = "resourceHAEnabled";
+
+ //////////////////////////////////////////////////////
+ //////////////// HA Manager methods //////////////////
+ //////////////////////////////////////////////////////
+
+ public Map<String, HAResourceCounter> haCounterMap = new ConcurrentHashMap<>();
+
+ public HAProvider<HAResource> getHAProvider(final String name) {
+ return haProviderMap.get(name);
+ }
+
+ private String resourceCounterKey(final Long resourceId, final HAResource.ResourceType resourceType) {
+ return resourceId.toString() + resourceType.toString();
+ }
+
+ public synchronized HAResourceCounter getHACounter(final Long resourceId, final HAResource.ResourceType resourceType) {
+ final String key = resourceCounterKey(resourceId, resourceType);
+ if (!haCounterMap.containsKey(key)) {
+ haCounterMap.put(key, new HAResourceCounter());
+ }
+ return haCounterMap.get(key);
+ }
+
+ public synchronized void purgeHACounter(final Long resourceId, final HAResource.ResourceType resourceType) {
+ final String key = resourceCounterKey(resourceId, resourceType);
+ if (haCounterMap.containsKey(key)) {
+ haCounterMap.remove(key);
+ }
+ }
+
+ public boolean transitionHAState(final HAConfig.Event event, final HAConfig haConfig) {
+ if (event == null || haConfig == null) {
+ return false;
+ }
+ final HAConfig.HAState currentHAState = haConfig.getState();
+ try {
+ final HAConfig.HAState nextState = HAConfig.HAState.getStateMachine().getNextState(currentHAState, event);
+ boolean result = HAConfig.HAState.getStateMachine().transitTo(haConfig, event, null, haConfigDao);
+ if (result) {
+ final String message = String.format("Transitioned host HA state from:%s to:%s due to event:%s for the host id:%d",
+ currentHAState, nextState, event, haConfig.getResourceId());
+ if (LOG.isTraceEnabled()) {
+ LOG.trace(message);
+ }
+ if (nextState == HAConfig.HAState.Recovering || nextState == HAConfig.HAState.Fencing || nextState == HAConfig.HAState.Fenced) {
+ ActionEventUtils.onActionEvent(CallContext.current().getCallingUserId(), CallContext.current().getCallingAccountId(),
+ Domain.ROOT_DOMAIN, EventTypes.EVENT_HA_STATE_TRANSITION, message);
+ }
+ }
+ return result;
+ } catch (NoTransitionException e) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Unable to find next HA state for current HA state: " + currentHAState + " for event: " + event + " for host" + haConfig.getResourceId());
+ }
+ }
+ return false;
+ }
+
+ private boolean transitionResourceStateToDisabled(final Partition partition) {
+ List<? extends HAResource> resources;
+ if (partition.partitionType() == Partition.PartitionType.Cluster) {
+ resources = hostDao.findByClusterId(partition.getId());
+ } else if (partition.partitionType() == Partition.PartitionType.Zone) {
+ resources = hostDao.findByDataCenterId(partition.getId());
+ } else {
+ return true;
+ }
+
+ boolean result = true;
+ for (final HAResource resource: resources) {
+ result = result && transitionHAState(HAConfig.Event.Disabled,
+ haConfigDao.findHAResource(resource.getId(), resource.resourceType()));
+ }
+ return result;
+ }
+
+ private boolean checkHAOwnership(final HAConfig haConfig) {
+ // Skip for resources not owned by this mgmt server
+ return !(haConfig.getManagementServerId() != null
+ && haConfig.getManagementServerId() != ManagementServerNode.getManagementServerId());
+ }
+
+ private HAResource validateAndFindHAResource(final HAConfig haConfig) {
+ HAResource resource = null;
+ if (haConfig.getResourceType() == HAResource.ResourceType.Host) {
+ final Host host = hostDao.findById(haConfig.getResourceId());
+ if (host != null && host.getRemoved() != null) {
+ return null;
+ }
+ resource = host;
+ if (resource == null && haConfig.getState() != HAConfig.HAState.Disabled) {
+ disableHA(haConfig.getResourceId(), haConfig.getResourceType());
+ return null;
+ }
+ }
+ if (!haConfig.isEnabled() || !isHAEnabledForZone(resource) || !isHAEnabledForCluster(resource)) {
+ if (haConfig.getState() != HAConfig.HAState.Disabled) {
+ if (transitionHAState(HAConfig.Event.Disabled, haConfig) ) {
+ purgeHACounter(haConfig.getResourceId(), haConfig.getResourceType());
+ }
+ }
+ return null;
+ } else if (haConfig.getState() == HAConfig.HAState.Disabled) {
+ transitionHAState(HAConfig.Event.Enabled, haConfig);
+ }
+ return resource;
+ }
+
+ private HAProvider<HAResource> validateAndFindHAProvider(final HAConfig haConfig, final HAResource resource) {
+ final HAProvider<HAResource> haProvider = haProviderMap.get(haConfig.getHaProvider());
+ if (haProvider != null && !haProvider.isEligible(resource)) {
+ if (haConfig.getState() != HAConfig.HAState.Ineligible) {
+ transitionHAState(HAConfig.Event.Ineligible, haConfig);
+ }
+ return null;
+ } else if (haConfig.getState() == HAConfig.HAState.Ineligible) {
+ transitionHAState(HAConfig.Event.Eligible, haConfig);
+ }
+ return haProvider;
+ }
+
+ public boolean isHAEnabledForZone(final HAResource resource) {
+ if (resource == null || resource.getDataCenterId() < 1L) {
+ return true;
+ }
+ final DataCenterDetailVO zoneDetails = dataCenterDetailsDao.findDetail(resource.getDataCenterId(), HA_ENABLED_DETAIL);
+ return zoneDetails == null || Strings.isNullOrEmpty(zoneDetails.getValue()) || Boolean.valueOf(zoneDetails.getValue());
+ }
+
+ private boolean isHAEnabledForCluster(final HAResource resource) {
+ if (resource == null || resource.getClusterId() == null) {
+ return true;
+ }
+ final ClusterDetailsVO clusterDetails = clusterDetailsDao.findDetail(resource.getClusterId(), HA_ENABLED_DETAIL);
+ return clusterDetails == null || Strings.isNullOrEmpty(clusterDetails.getValue()) || Boolean.valueOf(clusterDetails.getValue());
+ }
+
+ private boolean isHAEligibleForResource(final HAResource resource) {
+ if (resource == null || resource.getId() < 1L) {
+ return false;
+ }
+ HAResource.ResourceType resourceType = null;
+ if (resource instanceof Host) {
+ resourceType = HAResource.ResourceType.Host;
+ }
+ if (resourceType == null) {
+ return false;
+ }
+ final HAConfig haConfig = haConfigDao.findHAResource(resource.getId(), resourceType);
+ return haConfig != null && haConfig.isEnabled()
+ && haConfig.getState() != HAConfig.HAState.Disabled
+ && haConfig.getState() != HAConfig.HAState.Ineligible;
+ }
+
+ public boolean isHAEligible(final HAResource resource) {
+ return resource != null && isHAEnabledForZone(resource)
+ && isHAEnabledForCluster(resource)
+ && isHAEligibleForResource(resource);
+ }
+
+ public void validateHAProviderConfigForResource(final Long resourceId, final HAResource.ResourceType resourceType, final HAProvider<HAResource> haProvider) {
+ if (HAResource.ResourceType.Host.equals(resourceType)) {
+ final Host host = hostDao.findById(resourceId);
+ if (host.getHypervisorType() == null || haProvider.resourceSubType() == null || !host.getHypervisorType().toString().equals(haProvider.resourceSubType().toString())) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Incompatible haprovider provided for the resource of hypervisor type:" + host.getHypervisorType());
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////
+ //////////////// HA Investigator wrapper for Old HA ////////////////
+ ////////////////////////////////////////////////////////////////////
+
+ public Boolean isVMAliveOnHost(final Host host) throws Investigator.UnknownVM {
+ final HAConfig haConfig = haConfigDao.findHAResource(host.getId(), HAResource.ResourceType.Host);
+ if (haConfig != null) {
+ if (haConfig.getState() == HAConfig.HAState.Fenced) {
+ if (LOG.isDebugEnabled()){
+ LOG.debug("HA: Host is fenced " + host.getId());
+ }
+ return false;
+ }
+ if (LOG.isDebugEnabled()){
+ LOG.debug("HA: HOST is alive " + host.getId());
+ }
+ return true;
+ }
+ throw new Investigator.UnknownVM();
+ }
+
+ public Status getHostStatus(final Host host) {
+ final HAConfig haConfig = haConfigDao.findHAResource(host.getId(), HAResource.ResourceType.Host);
+ if (haConfig != null) {
+ if (haConfig.getState() == HAConfig.HAState.Fenced) {
+ if (LOG.isDebugEnabled()){
+ LOG.debug("HA: Agent is available/suspect/checking Up " + host.getId());
+ }
+ return Status.Down;
+ } else if (haConfig.getState() == HAConfig.HAState.Degraded || haConfig.getState() == HAConfig.HAState.Recovering || haConfig.getState() == HAConfig.HAState.Fencing) {
+ if (LOG.isDebugEnabled()){
+ LOG.debug("HA: Agent is disconnected " + host.getId());
+ }
+ return Status.Disconnected;
+ }
+ return Status.Up;
+ }
+ return Status.Unknown;
+ }
+
+ //////////////////////////////////////////////////////
+ //////////////// HA API handlers /////////////////////
+ //////////////////////////////////////////////////////
+
+ private boolean configureHA(final Long resourceId, final HAResource.ResourceType resourceType, final Boolean enable, final String haProvider) {
+ return Transaction.execute(new TransactionCallback<Boolean>() {
+ @Override
+ public Boolean doInTransaction(TransactionStatus status) {
+ HAConfigVO haConfig = (HAConfigVO) haConfigDao.findHAResource(resourceId, resourceType);
+ if (haConfig == null) {
+ haConfig = new HAConfigVO();
+ if (haProvider != null) {
+ haConfig.setHaProvider(haProvider);
+ }
+ if (enable != null) {
+ haConfig.setEnabled(enable);
+ haConfig.setManagementServerId(ManagementServerNode.getManagementServerId());
+ }
+ haConfig.setResourceId(resourceId);
+ haConfig.setResourceType(resourceType);
+ if (Strings.isNullOrEmpty(haConfig.getHaProvider())) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "HAProvider is not provided for the resource, failing configuration.");
+ }
+ if (haConfigDao.persist(haConfig) != null) {
+ return true;
+ }
+ } else {
+ if (enable != null) {
+ haConfig.setEnabled(enable);
+ }
+ if (haProvider != null) {
+ haConfig.setHaProvider(haProvider);
+ }
+ if (Strings.isNullOrEmpty(haConfig.getHaProvider())) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "HAProvider is not provided for the resource, failing configuration.");
+ }
+ return haConfigDao.update(haConfig.getId(), haConfig);
+ }
+ return false;
+ }
+ });
+ }
+
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_HA_RESOURCE_CONFIGURE, eventDescription = "configuring HA for resource")
+ public boolean configureHA(final Long resourceId, final HAResource.ResourceType resourceType, final String haProvider) {
+ Preconditions.checkArgument(resourceId != null && resourceId > 0L);
+ Preconditions.checkArgument(resourceType != null);
+ Preconditions.checkArgument(!Strings.isNullOrEmpty(haProvider));
+
+ if (!haProviderMap.containsKey(haProvider.toLowerCase())) {
+ throw new CloudRuntimeException("Given HA provider does not exist.");
+ }
+ validateHAProviderConfigForResource(resourceId, resourceType, haProviderMap.get(haProvider.toLowerCase()));
+ return configureHA(resourceId, resourceType, null, haProvider.toLowerCase());
+ }
+
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_HA_RESOURCE_ENABLE, eventDescription = "enabling HA for resource")
+ public boolean enableHA(final Long resourceId, final HAResource.ResourceType resourceType) {
+ Preconditions.checkArgument(resourceId != null && resourceId > 0L);
+ Preconditions.checkArgument(resourceType != null);
+ return configureHA(resourceId, resourceType, true, null);
+ }
+
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_HA_RESOURCE_DISABLE, eventDescription = "disabling HA for resource")
+ public boolean disableHA(final Long resourceId, final HAResource.ResourceType resourceType) {
+ Preconditions.checkArgument(resourceId != null && resourceId > 0L);
+ Preconditions.checkArgument(resourceType != null);
+ boolean result = configureHA(resourceId, resourceType, false, null);
+ if (result) {
+ transitionHAState(HAConfig.Event.Disabled, haConfigDao.findHAResource(resourceId, resourceType));
+ purgeHACounter(resourceId, resourceType);
+ }
+ return result;
+ }
+
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_HA_RESOURCE_ENABLE, eventDescription = "enabling HA for a cluster")
+ public boolean enableHA(final Cluster cluster) {
+ clusterDetailsDao.persist(cluster.getId(), HA_ENABLED_DETAIL, String.valueOf(true));
+ return true;
+ }
+
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_HA_RESOURCE_DISABLE, eventDescription = "disabling HA for a cluster")
+ public boolean disableHA(final Cluster cluster) {
+ clusterDetailsDao.persist(cluster.getId(), HA_ENABLED_DETAIL, String.valueOf(false));
+ return transitionResourceStateToDisabled(cluster);
+ }
+
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_HA_RESOURCE_ENABLE, eventDescription = "enabling HA for a zone")
+ public boolean enableHA(final DataCenter zone) {
+ dataCenterDetailsDao.persist(zone.getId(), HA_ENABLED_DETAIL, String.valueOf(true));
+ return true;
+ }
+
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_HA_RESOURCE_DISABLE, eventDescription = "disabling HA for a zone")
+ public boolean disableHA(final DataCenter zone) {
+ dataCenterDetailsDao.persist(zone.getId(), HA_ENABLED_DETAIL, String.valueOf(false));
+ return transitionResourceStateToDisabled(zone);
+ }
+
+ @Override
+ public List<HAConfig> listHAResources(final Long resourceId, final HAResource.ResourceType resourceType) {
+ return haConfigDao.listHAResource(resourceId, resourceType);
+ }
+
+ @Override
+ public List<String> listHAProviders(final HAResource.ResourceType resourceType, final HAResource.ResourceSubType entityType) {
+ final List<String> haProviderNames = new ArrayList<>();
+ for (final HAProvider<HAResource> haProvider : haProviders) {
+ if (haProvider.resourceType().equals(resourceType) && haProvider.resourceSubType().equals(entityType)) {
+ haProviderNames.add(haProvider.getClass().getSimpleName());
+ }
+ }
+ return haProviderNames;
+ }
+
+ @Override
+ public List<Class<?>> getCommands() {
+ List<Class<?>> cmdList = new ArrayList<>();
+ cmdList.add(ConfigureHAForHostCmd.class);
+ cmdList.add(EnableHAForHostCmd.class);
+ cmdList.add(EnableHAForClusterCmd.class);
+ cmdList.add(EnableHAForZoneCmd.class);
+ cmdList.add(DisableHAForHostCmd.class);
+ cmdList.add(DisableHAForClusterCmd.class);
+ cmdList.add(DisableHAForZoneCmd.class);
+ cmdList.add(ListHostHAResourcesCmd.class);
+ cmdList.add(ListHostHAProvidersCmd.class);
+ return cmdList;
+ }
+
+ //////////////////////////////////////////////////////
+ //////////////// Event Listeners /////////////////////
+ //////////////////////////////////////////////////////
+
+ @Override
+ public void onManagementNodeJoined(List<? extends ManagementServerHost> nodeList, long selfNodeId) {
+ }
+
+ @Override
+ public void onManagementNodeLeft(List<? extends ManagementServerHost> nodeList, long selfNodeId) {
+ }
+
+ @Override
+ public void onManagementNodeIsolated() {
+ }
+
+ private boolean processHAStateChange(final HAConfig haConfig, final HAConfig.HAState newState, final boolean status) {
+ if (!status || !checkHAOwnership(haConfig)) {
+ return false;
+ }
+
+ final HAResource resource = validateAndFindHAResource(haConfig);
+ if (resource == null) {
+ return false;
+ }
+
+ final HAProvider<HAResource> haProvider = validateAndFindHAProvider(haConfig, resource);
+ if (haProvider == null) {
+ return false;
+ }
+
+ final HAResourceCounter counter = getHACounter(haConfig.getResourceId(), haConfig.getResourceType());
+
+ // Perform activity checks
+ if (newState == HAConfig.HAState.Checking) {
+ final ActivityCheckTask job = ComponentContext.inject(new ActivityCheckTask(resource, haProvider, haConfig,
+ HAProviderConfig.ActivityCheckTimeout, activityCheckExecutor, counter.getSuspectTimeStamp()));
+ activityCheckExecutor.submit(job);
+ }
+
+ // Attempt recovery
+ if (newState == HAConfig.HAState.Recovering) {
+ if (counter.getRecoveryCounter() >= (Long) (haProvider.getConfigValue(HAProviderConfig.MaxRecoveryAttempts, resource))) {
+ return false;
+ }
+ final RecoveryTask task = ComponentContext.inject(new RecoveryTask(resource, haProvider, haConfig,
+ HAProviderConfig.RecoveryTimeout, recoveryExecutor));
+ final Future<Boolean> recoveryFuture = recoveryExecutor.submit(task);
+ counter.setRecoveryFuture(recoveryFuture);
+ }
+
+ // Fencing
+ if (newState == HAConfig.HAState.Fencing) {
+ final FenceTask task = ComponentContext.inject(new FenceTask(resource, haProvider, haConfig,
+ HAProviderConfig.FenceTimeout, fenceExecutor));
+ final Future<Boolean> fenceFuture = fenceExecutor.submit(task);
+ counter.setFenceFuture(fenceFuture);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean preStateTransitionEvent(final HAConfig.HAState oldState, final HAConfig.Event event, final HAConfig.HAState newState, final HAConfig haConfig, final boolean status, final Object opaque) {
+ if (oldState != newState || newState == HAConfig.HAState.Suspect || newState == HAConfig.HAState.Checking) {
+ return false;
+ }
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("HA state pre-transition:: new state=" + newState + ", old state=" + oldState + ", for resource id=" + haConfig.getResourceId() + ", status=" + status + ", ha config state=" + haConfig.getState());
+ }
+ if (status && haConfig.getState() != newState) {
+ LOG.warn("HA state pre-transition:: HA state is not equal to transition state, HA state=" + haConfig.getState() + ", new state=" + newState);
+ }
+ return processHAStateChange(haConfig, newState, status);
+ }
+
+ @Override
+ public boolean postStateTransitionEvent(final StateMachine2.Transition<HAConfig.HAState, HAConfig.Event> transition, final HAConfig haConfig, final boolean status, final Object opaque) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("HA state post-transition:: new state=" + transition.getToState() + ", old state=" + transition.getCurrentState() + ", for resource id=" + haConfig.getResourceId() + ", status=" + status + ", ha config state=" + haConfig.getState());
+ }
+ if (status && haConfig.getState() != transition.getToState()) {
+ LOG.warn("HA state post-transition:: HA state is not equal to transition state, HA state=" + haConfig.getState() + ", new state=" + transition.getToState());
+ }
+ return processHAStateChange(haConfig, transition.getToState(), status);
+ }
+
+ ///////////////////////////////////////////////////
+ //////////////// Manager Init /////////////////////
+ ///////////////////////////////////////////////////
+
+ @Override
+ public boolean start() {
+ haProviderMap.clear();
+ for (final HAProvider<HAResource> haProvider : haProviders) {
+ haProviderMap.put(haProvider.getClass().getSimpleName().toLowerCase(), haProvider);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean stop() {
+ haConfigDao.expireServerOwnership(ManagementServerNode.getManagementServerId());
+ return true;
+ }
+
+ @Override
+ public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
+ // Health Check
+ final int healthCheckWorkers = MaxConcurrentHealthCheckOperations.value();
+ final int healthCheckQueueSize = MaxPendingHealthCheckOperations.value();
+ healthCheckExecutor = new ThreadPoolExecutor(healthCheckWorkers, healthCheckWorkers,
+ 0L, TimeUnit.MILLISECONDS,
+ new ArrayBlockingQueue<Runnable>(healthCheckQueueSize, true), new ThreadPoolExecutor.CallerRunsPolicy());
+
+ // Activity Check
+ final int activityCheckWorkers = MaxConcurrentActivityCheckOperations.value();
+ final int activityCheckQueueSize = MaxPendingActivityCheckOperations.value();
+ activityCheckExecutor = new ThreadPoolExecutor(activityCheckWorkers, activityCheckWorkers,
+ 0L, TimeUnit.MILLISECONDS,
+ new ArrayBlockingQueue<Runnable>(activityCheckQueueSize, true), new ThreadPoolExecutor.CallerRunsPolicy());
+
+ // Recovery
+ final int recoveryOperationWorkers = MaxConcurrentRecoveryOperations.value();
+ final int recoveryOperationQueueSize = MaxPendingRecoveryOperations.value();
+ recoveryExecutor = new ThreadPoolExecutor(recoveryOperationWorkers, recoveryOperationWorkers,
+ 0L, TimeUnit.MILLISECONDS,
+ new ArrayBlockingQueue<Runnable>(recoveryOperationQueueSize, true), new ThreadPoolExecutor.CallerRunsPolicy());
+
+ // Fence
+ final int fenceOperationWorkers = MaxConcurrentFenceOperations.value();
+ final int fenceOperationQueueSize = MaxPendingFenceOperations.value();
+ fenceExecutor = new ThreadPoolExecutor(fenceOperationWorkers, fenceOperationWorkers,
+ 0L, TimeUnit.MILLISECONDS,
+ new ArrayBlockingQueue<Runnable>(fenceOperationQueueSize, true), new ThreadPoolExecutor.CallerRunsPolicy());
+
+ pollManager.submitTask(new HAManagerBgPollTask());
+ HAConfig.HAState.getStateMachine().registerListener(this);
+
+ LOG.debug("HA manager has been configured");
+ return true;
+ }
+
+ public void setHaProviders(List<HAProvider<HAResource>> haProviders) {
+ this.haProviders = haProviders;
+ }
+
+ @Override
+ public String getConfigComponentName() {
+ return HAManager.class.getSimpleName();
+ }
+
+ @Override
+ public ConfigKey<?>[] getConfigKeys() {
+ return new ConfigKey<?>[] {
+ MaxConcurrentHealthCheckOperations,
+ MaxPendingHealthCheckOperations,
+ MaxConcurrentActivityCheckOperations,
+ MaxPendingActivityCheckOperations,
+ MaxConcurrentRecoveryOperations,
+ MaxPendingRecoveryOperations,
+ MaxConcurrentFenceOperations,
+ MaxPendingFenceOperations
+ };
+ }
+
+ /////////////////////////////////////////////////
+ //////////////// Poll Tasks /////////////////////
+ /////////////////////////////////////////////////
+
+ private final class HAManagerBgPollTask extends ManagedContextRunnable implements BackgroundPollTask {
+ @Override
+ protected void runInContext() {
+ try {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("HA health check task is running...");
+ }
+ final List<HAConfig> haConfigList = new ArrayList<HAConfig>(haConfigDao.listAll());
+ for (final HAConfig haConfig : haConfigList) {
+ if (!checkHAOwnership(haConfig)) {
+ continue;
+ }
+
+ final HAResource resource = validateAndFindHAResource(haConfig);
+ if (resource == null) {
+ continue;
+ }
+
+ final HAProvider<HAResource> haProvider = validateAndFindHAProvider(haConfig, resource);
+ if (haProvider == null) {
+ continue;
+ }
+
+ switch (haConfig.getState()) {
+ case Available:
+ case Suspect:
+ case Degraded:
+ case Fenced:
+ final HealthCheckTask task = ComponentContext.inject(new HealthCheckTask(resource, haProvider, haConfig,
+ HAProviderConfig.HealthCheckTimeout, healthCheckExecutor));
+ healthCheckExecutor.submit(task);
+ break;
+ default:
+ break;
+ }
+
+ final HAResourceCounter counter = getHACounter(haConfig.getResourceId(), haConfig.getResourceType());
+
+ if (haConfig.getState() == HAConfig.HAState.Suspect) {
+ if (counter.canPerformActivityCheck((Long)(haProvider.getConfigValue(HAProviderConfig.MaxActivityCheckInterval, resource)))) {
+ transitionHAState(HAConfig.Event.PerformActivityCheck, haConfig);
+ }
+ }
+
+ if (haConfig.getState() == HAConfig.HAState.Degraded) {
+ if (counter.canRecheckActivity((Long)(haProvider.getConfigValue(HAProviderConfig.MaxDegradedWaitTimeout, resource)))) {
+ transitionHAState(HAConfig.Event.PeriodicRecheckResourceActivity, haConfig);
+ }
+ }
+
+ if (haConfig.getState() == HAConfig.HAState.Recovering) {
+ if (counter.getRecoveryCounter() >= (Long) (haProvider.getConfigValue(HAProviderConfig.MaxRecoveryAttempts, resource))) {
+ transitionHAState(HAConfig.Event.RecoveryOperationThresholdExceeded, haConfig);
+ } else {
+ transitionHAState(HAConfig.Event.RetryRecovery, haConfig);
+ }
+ }
+
+ if (haConfig.getState() == HAConfig.HAState.Recovered) {
+ counter.markRecoveryStarted();
+ if (counter.canExitRecovery((Long)(haProvider.getConfigValue(HAProviderConfig.RecoveryWaitTimeout, resource)))) {
+ if (transitionHAState(HAConfig.Event.RecoveryWaitPeriodTimeout, haConfig)) {
+ counter.markRecoveryCompleted();
+ }
+ }
+ }
+
+ if (haConfig.getState() == HAConfig.HAState.Fencing && counter.canAttemptFencing()) {
+ transitionHAState(HAConfig.Event.RetryFencing, haConfig);
+ }
+ }
+ } catch (Throwable t) {
+ LOG.error("Error trying to perform health checks in HA manager", t);
+ }
+ }
+
+ @Override
+ public Long getDelay() {
+ return null;
+ }
+ }
+}
diff --git a/server/src/org/apache/cloudstack/ha/HAResourceCounter.java b/server/src/org/apache/cloudstack/ha/HAResourceCounter.java
new file mode 100644
index 00000000000..f493f6926e0
--- /dev/null
+++ b/server/src/org/apache/cloudstack/ha/HAResourceCounter.java
@@ -0,0 +1,131 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ha;
+
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicLong;
+
+public final class HAResourceCounter {
+ private AtomicLong activityCheckCounter = new AtomicLong(0);
+ private AtomicLong activityCheckFailureCounter = new AtomicLong(0);
+ private AtomicLong recoveryOperationCounter = new AtomicLong(0);
+
+ private Long firstHealthCheckFailureTimestamp;
+ private Long lastActivityCheckTimestamp;
+ private Long degradedTimestamp;
+ private Long recoverTimestamp;
+ private Future<Boolean> recoveryFuture;
+ private Future<Boolean> fenceFuture;
+
+ public long getActivityCheckCounter() {
+ return activityCheckCounter.get();
+ }
+
+ public long getRecoveryCounter() {
+ return recoveryOperationCounter.get();
+ }
+
+ public synchronized void incrActivityCounter(final boolean isFailure) {
+ activityCheckCounter.incrementAndGet();
+ if (isFailure) {
+ activityCheckFailureCounter.incrementAndGet();
+ }
+ }
+
+ public synchronized void incrRecoveryCounter() {
+ recoveryOperationCounter.incrementAndGet();
+ }
+
+ public synchronized void resetActivityCounter() {
+ activityCheckCounter.set(0);
+ activityCheckFailureCounter.set(0);
+ }
+
+ public synchronized void resetRecoveryCounter() {
+ recoverTimestamp = null;
+ recoveryFuture = null;
+ recoveryOperationCounter.set(0);
+ }
+
+ public synchronized void resetSuspectTimestamp() {
+ firstHealthCheckFailureTimestamp = null;
+ }
+
+ public boolean hasActivityThresholdExceeded(final double failureRatio) {
+ return activityCheckFailureCounter.get() > (activityCheckCounter.get() * failureRatio);
+ }
+
+ public synchronized boolean canPerformActivityCheck(final Long activityCheckInterval) {
+ if (lastActivityCheckTimestamp == null || (System.currentTimeMillis() - lastActivityCheckTimestamp) > (activityCheckInterval * 1000)) {
+ lastActivityCheckTimestamp = System.currentTimeMillis();
+ return true;
+ }
+ return false;
+ }
+
+ public boolean canRecheckActivity(final Long maxDegradedPeriod) {
+ return degradedTimestamp == null || (System.currentTimeMillis() - degradedTimestamp) > (maxDegradedPeriod * 1000);
+ }
+
+ public boolean canExitRecovery(final Long maxRecoveryWaitPeriod) {
+ return recoverTimestamp != null && (System.currentTimeMillis() - recoverTimestamp) > (maxRecoveryWaitPeriod * 1000);
+ }
+
+ public long getSuspectTimeStamp() {
+ if (firstHealthCheckFailureTimestamp == null) {
+ firstHealthCheckFailureTimestamp = System.currentTimeMillis();
+ }
+ return firstHealthCheckFailureTimestamp;
+ }
+
+ public synchronized void markResourceSuspected() {
+ firstHealthCheckFailureTimestamp = System.currentTimeMillis();
+ }
+
+ public synchronized void markResourceDegraded() {
+ degradedTimestamp = System.currentTimeMillis();
+ }
+
+ public synchronized void markRecoveryStarted() {
+ if (recoverTimestamp == null) {
+ recoverTimestamp = System.currentTimeMillis();
+ }
+ }
+
+ public synchronized void markRecoveryCompleted() {
+ recoverTimestamp = null;
+ recoveryFuture = null;
+ }
+
+ public void setRecoveryFuture(final Future<Boolean> future) {
+ recoveryFuture = future;
+ }
+
+ public boolean canAttemptRecovery() {
+ return recoveryFuture == null || recoveryFuture.isDone();
+ }
+
+ public void setFenceFuture(final Future<Boolean> future) {
+ fenceFuture = future;
+ }
+
+ public boolean canAttemptFencing() {
+ return fenceFuture == null || fenceFuture.isDone();
+ }
+
+}
diff --git a/server/src/org/apache/cloudstack/ha/provider/ActivityCheckerInterface.java b/server/src/org/apache/cloudstack/ha/provider/ActivityCheckerInterface.java
new file mode 100644
index 00000000000..1f280297436
--- /dev/null
+++ b/server/src/org/apache/cloudstack/ha/provider/ActivityCheckerInterface.java
@@ -0,0 +1,35 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ha.provider;
+
+import org.joda.time.DateTime;
+
+import org.apache.cloudstack.ha.HAResource;
+
+import com.cloud.utils.component.Adapter;
+
+/**
+ * Checking activity requires deeper investigation. This will be invoked when a health check has failed.
+ *
+ * @param <R>
+ */
+public interface ActivityCheckerInterface<R extends HAResource> extends Adapter {
+
+ boolean isActive(R r, DateTime t) throws HACheckerException ;
+
+}
diff --git a/server/src/org/apache/cloudstack/ha/provider/HACheckerException.java b/server/src/org/apache/cloudstack/ha/provider/HACheckerException.java
new file mode 100644
index 00000000000..9e736221d63
--- /dev/null
+++ b/server/src/org/apache/cloudstack/ha/provider/HACheckerException.java
@@ -0,0 +1,29 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+
+package org.apache.cloudstack.ha.provider;
+
+public class HACheckerException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public HACheckerException(String string, Exception e) {
+ super(string, e);
+ }
+
+}
diff --git a/server/src/org/apache/cloudstack/ha/provider/HAFenceException.java b/server/src/org/apache/cloudstack/ha/provider/HAFenceException.java
new file mode 100644
index 00000000000..80a7c3be92a
--- /dev/null
+++ b/server/src/org/apache/cloudstack/ha/provider/HAFenceException.java
@@ -0,0 +1,29 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+
+package org.apache.cloudstack.ha.provider;
+
+public class HAFenceException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public HAFenceException(String string, Exception e) {
+ super(string, e);
+ }
+
+}
diff --git a/server/src/org/apache/cloudstack/ha/provider/HAProvider.java b/server/src/org/apache/cloudstack/ha/provider/HAProvider.java
new file mode 100644
index 00000000000..9a7f27c003e
--- /dev/null
+++ b/server/src/org/apache/cloudstack/ha/provider/HAProvider.java
@@ -0,0 +1,66 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ha.provider;
+
+import org.apache.cloudstack.ha.HAConfig;
+import org.apache.cloudstack.ha.HAResource;
+import org.joda.time.DateTime;
+
+import com.cloud.utils.component.Adapter;
+
+public interface HAProvider<R extends HAResource> extends Adapter {
+
+ enum HAProviderConfig {
+ HealthCheckTimeout,
+ ActivityCheckTimeout,
+ RecoveryTimeout,
+ FenceTimeout,
+ ActivityCheckFailureRatio,
+ MaxActivityChecks,
+ MaxRecoveryAttempts,
+ MaxActivityCheckInterval,
+ MaxDegradedWaitTimeout,
+ RecoveryWaitTimeout
+ };
+
+ HAResource.ResourceType resourceType();
+
+ HAResource.ResourceSubType resourceSubType();
+
+ boolean isDisabled(R r);
+
+ boolean isInMaintenanceMode(R r);
+
+ boolean isEligible(R r);
+
+ boolean isHealthy(R r) throws HACheckerException;
+
+ boolean hasActivity(R r, DateTime afterThis) throws HACheckerException;
+
+ boolean recover(R r) throws HARecoveryException;
+
+ boolean fence(R r) throws HAFenceException;
+
+ void fenceSubResources(R r);
+
+ void enableMaintenance(R r);
+
+ void sendAlert(R r, HAConfig.HAState nextState);
+
+ Object getConfigValue(HAProviderConfig name, R r);
+}
diff --git a/server/src/org/apache/cloudstack/ha/provider/HARecoveryException.java b/server/src/org/apache/cloudstack/ha/provider/HARecoveryException.java
new file mode 100644
index 00000000000..893e21c7230
--- /dev/null
+++ b/server/src/org/apache/cloudstack/ha/provider/HARecoveryException.java
@@ -0,0 +1,28 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ha.provider;
+
+public class HARecoveryException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public HARecoveryException(String string, Exception e) {
+ super(string, e);
+ }
+
+}
diff --git a/server/src/org/apache/cloudstack/ha/provider/HealthCheckerInterface.java b/server/src/org/apache/cloudstack/ha/provider/HealthCheckerInterface.java
new file mode 100644
index 00000000000..ec0a5810214
--- /dev/null
+++ b/server/src/org/apache/cloudstack/ha/provider/HealthCheckerInterface.java
@@ -0,0 +1,34 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ha.provider;
+
+import org.apache.cloudstack.ha.HAResource;
+
+import com.cloud.utils.component.Adapter;
+
+/**
+ * Health checker is a quick way to find out if a resource is active. Like pinging the host or checking agent health.
+ *
+ * @param <R>
+ */
+
+public interface HealthCheckerInterface<R extends HAResource> extends Adapter {
+
+ boolean isHealthy(R r);
+
+}
diff --git a/server/src/org/apache/cloudstack/ha/provider/HostHAProvider.java b/server/src/org/apache/cloudstack/ha/provider/HostHAProvider.java
new file mode 100644
index 00000000000..4867d92f35d
--- /dev/null
+++ b/server/src/org/apache/cloudstack/ha/provider/HostHAProvider.java
@@ -0,0 +1,23 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ha.provider;
+
+import com.cloud.host.Host;
+
+public interface HostHAProvider extends HAProvider<Host> {
+}
diff --git a/server/src/org/apache/cloudstack/ha/provider/host/HAAbstractHostProvider.java b/server/src/org/apache/cloudstack/ha/provider/host/HAAbstractHostProvider.java
new file mode 100644
index 00000000000..966c2843e65
--- /dev/null
+++ b/server/src/org/apache/cloudstack/ha/provider/host/HAAbstractHostProvider.java
@@ -0,0 +1,109 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ha.provider.host;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.alert.AlertManager;
+import com.cloud.ha.HighAvailabilityManager;
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+import com.cloud.host.Status;
+import com.cloud.host.Status.Event;
+import com.cloud.resource.ResourceManager;
+import com.cloud.resource.ResourceState;
+import com.cloud.utils.component.AdapterBase;
+import com.cloud.utils.fsm.NoTransitionException;
+import org.apache.cloudstack.alert.AlertService;
+import org.apache.cloudstack.ha.HAConfig;
+import org.apache.cloudstack.ha.HAResource;
+import org.apache.cloudstack.ha.provider.HAProvider;
+import org.apache.cloudstack.utils.identity.ManagementServerNode;
+import org.apache.log4j.Logger;
+
+import javax.inject.Inject;
+
+public abstract class HAAbstractHostProvider extends AdapterBase implements HAProvider<Host> {
+
+ private final static Logger LOG = Logger.getLogger(HAAbstractHostProvider.class);
+
+ @Inject
+ private AlertManager alertManager;
+ @Inject
+ protected AgentManager agentManager;
+ @Inject
+ protected ResourceManager resourceManager;
+ @Inject
+ protected HighAvailabilityManager oldHighAvailabilityManager;
+
+
+ @Override
+ public HAResource.ResourceType resourceType() {
+ return HAResource.ResourceType.Host;
+ }
+
+ public HAResource.ResourceSubType resourceSubType() {
+ return HAResource.ResourceSubType.Unknown;
+ }
+
+ @Override
+ public boolean isDisabled(final Host host) {
+ return host.isDisabled();
+ }
+
+ @Override
+ public boolean isInMaintenanceMode(final Host host) {
+ return host.isInMaintenanceStates();
+ }
+
+ @Override
+ public void fenceSubResources(final Host r) {
+ if (r.getState() != Status.Down) {
+ try {
+ LOG.debug("Trying to disconnect the host without investigation and scheduling HA for the VMs on host id=" + r.getId());
+ agentManager.disconnectWithoutInvestigation(r.getId(), Event.HostDown);
+ oldHighAvailabilityManager.scheduleRestartForVmsOnHost((HostVO)r, true);
+ } catch (Exception e) {
+ LOG.error("Failed to disconnect host and schedule HA restart of VMs after fencing the host: ", e);
+ }
+ }
+ }
+
+ @Override
+ public void enableMaintenance(final Host r) {
+ try {
+ resourceManager.resourceStateTransitTo(r, ResourceState.Event.InternalEnterMaintenance, ManagementServerNode.getManagementServerId());
+ } catch (NoTransitionException e) {
+ LOG.error("Failed to put host in maintenance mode after host-ha fencing and scheduling VM-HA: ", e);
+ }
+ }
+
+ @Override
+ public void sendAlert(final Host host, final HAConfig.HAState nextState) {
+ String subject = "HA operation performed for host";
+ String body = subject;
+ if (HAConfig.HAState.Fencing.equals(nextState)) {
+ subject = String.format("HA Fencing of host id=%d, in dc id=%d performed", host.getId(), host.getDataCenterId());
+ body = String.format("HA Fencing has been performed for host id=%d, uuid=%s in datacenter id=%d", host.getId(), host.getUuid(), host.getDataCenterId());
+ } else if (HAConfig.HAState.Recovering.equals(nextState)) {
+ subject = String.format("HA Recovery of host id=%d, in dc id=%d performed", host.getId(), host.getDataCenterId());
+ body = String.format("HA Recovery has been performed for host id=%d, uuid=%s in datacenter id=%d", host.getId(), host.getUuid(), host.getDataCenterId());
+ }
+ alertManager.sendAlert(AlertService.AlertType.ALERT_TYPE_HA_ACTION, host.getDataCenterId(), host.getPodId(), subject, body);
+ }
+
+}
diff --git a/server/src/org/apache/cloudstack/ha/task/ActivityCheckTask.java b/server/src/org/apache/cloudstack/ha/task/ActivityCheckTask.java
new file mode 100644
index 00000000000..24f96963262
--- /dev/null
+++ b/server/src/org/apache/cloudstack/ha/task/ActivityCheckTask.java
@@ -0,0 +1,83 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ha.task;
+
+import java.util.concurrent.ExecutorService;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.ha.HAConfig;
+import org.apache.cloudstack.ha.HAManager;
+import org.apache.cloudstack.ha.HAResource;
+import org.apache.cloudstack.ha.HAResourceCounter;
+import org.apache.cloudstack.ha.provider.HACheckerException;
+import org.apache.cloudstack.ha.provider.HAProvider;
+import org.apache.cloudstack.ha.provider.HAProvider.HAProviderConfig;
+import org.apache.log4j.Logger;
+import org.joda.time.DateTime;
+
+public class ActivityCheckTask extends BaseHATask {
+
+ public static final Logger LOG = Logger.getLogger(ActivityCheckTask.class);
+
+ @Inject
+ private HAManager haManager;
+
+ private long disconnectTime;
+ private long maxActivityChecks;
+ private double activityCheckFailureRatio;
+
+ public ActivityCheckTask(final HAResource resource, final HAProvider<HAResource> haProvider, final HAConfig haConfig, final HAProvider.HAProviderConfig haProviderConfig,
+ final ExecutorService executor, final long disconnectTime) {
+ super(resource, haProvider, haConfig, haProviderConfig, executor);
+ this.disconnectTime = disconnectTime;
+ this.maxActivityChecks = (Long)haProvider.getConfigValue(HAProviderConfig.MaxActivityChecks, resource);
+ this.activityCheckFailureRatio = (Double)haProvider.getConfigValue(HAProviderConfig.ActivityCheckFailureRatio, resource);
+ }
+
+ public boolean performAction() throws HACheckerException {
+ return getHaProvider().hasActivity(getResource(), new DateTime(disconnectTime));
+ }
+
+ public synchronized void processResult(boolean result, Throwable t) {
+ final HAConfig haConfig = getHaConfig();
+ final HAResourceCounter counter = haManager.getHACounter(haConfig.getResourceId(), haConfig.getResourceType());
+
+ if (t != null && t instanceof HACheckerException) {
+ haManager.transitionHAState(HAConfig.Event.Ineligible, getHaConfig());
+ counter.resetActivityCounter();
+ return;
+ }
+
+ counter.incrActivityCounter(!result);
+
+ if (counter.getActivityCheckCounter() < maxActivityChecks) {
+ haManager.transitionHAState(HAConfig.Event.TooFewActivityCheckSamples, haConfig);
+ return;
+ }
+
+ if (counter.hasActivityThresholdExceeded(activityCheckFailureRatio)) {
+ haManager.transitionHAState(HAConfig.Event.ActivityCheckFailureOverThresholdRatio, haConfig);
+ } else {
+ if (haManager.transitionHAState(HAConfig.Event.ActivityCheckFailureUnderThresholdRatio, haConfig)) {
+ counter.markResourceDegraded();
+ }
+ }
+ counter.resetActivityCounter();
+ }
+}
diff --git a/server/src/org/apache/cloudstack/ha/task/BaseHATask.java b/server/src/org/apache/cloudstack/ha/task/BaseHATask.java
new file mode 100644
index 00000000000..9c878092a54
--- /dev/null
+++ b/server/src/org/apache/cloudstack/ha/task/BaseHATask.java
@@ -0,0 +1,111 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ha.task;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.cloudstack.ha.HAConfig;
+import org.apache.cloudstack.ha.HAResource;
+import org.apache.cloudstack.ha.provider.HACheckerException;
+import org.apache.cloudstack.ha.provider.HAFenceException;
+import org.apache.cloudstack.ha.provider.HAProvider;
+import org.apache.cloudstack.ha.provider.HARecoveryException;
+import org.apache.log4j.Logger;
+import org.joda.time.DateTime;
+
+public abstract class BaseHATask implements Callable<Boolean> {
+ public static final Logger LOG = Logger.getLogger(BaseHATask.class);
+
+ private final HAResource resource;
+ private final HAProvider<HAResource> haProvider;
+ private final HAConfig haConfig;
+ private final ExecutorService executor;
+ private Long timeout;
+ private DateTime created;
+
+ public BaseHATask(final HAResource resource, final HAProvider<HAResource> haProvider, final HAConfig haConfig, final HAProvider.HAProviderConfig haProviderConfig,
+ final ExecutorService executor) {
+ this.resource = resource;
+ this.haProvider = haProvider;
+ this.haConfig = haConfig;
+ this.executor = executor;
+ this.timeout = (Long)haProvider.getConfigValue(haProviderConfig, resource);
+ this.created = new DateTime();
+ }
+
+ public HAProvider<HAResource> getHaProvider() {
+ return haProvider;
+ }
+
+ public HAConfig getHaConfig() {
+ return haConfig;
+ }
+
+ public HAResource getResource() {
+ return resource;
+ }
+
+ public String getTaskType() {
+ return this.getClass().getSimpleName();
+ }
+
+ public boolean performAction() throws HACheckerException, HAFenceException, HARecoveryException {
+ return true;
+ }
+
+ public abstract void processResult(boolean result, Throwable e);
+
+ @Override
+ public Boolean call() {
+ if (new DateTime().minusHours(1).isAfter(getCreated())) {
+ return false;
+ }
+ final Future<Boolean> future = executor.submit(new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws HACheckerException, HAFenceException, HARecoveryException {
+ return performAction();
+ }
+ });
+
+ boolean result = false;
+ Throwable throwable = null;
+ try {
+ if (timeout == null) {
+ result = future.get();
+ } else {
+ result = future.get(timeout, TimeUnit.SECONDS);
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception occurred while running " + getTaskType() + " on a resource: " + e.getMessage(), e.getCause());
+ throwable = e.getCause();
+ } catch (TimeoutException e) {
+ LOG.trace(getTaskType() + " operation timed out for resource id:" + resource.getId());
+ }
+ processResult(result, throwable);
+ return result;
+ }
+
+ public DateTime getCreated() {
+ return created;
+ }
+}
diff --git a/server/src/org/apache/cloudstack/ha/task/FenceTask.java b/server/src/org/apache/cloudstack/ha/task/FenceTask.java
new file mode 100644
index 00000000000..700d6b8eef3
--- /dev/null
+++ b/server/src/org/apache/cloudstack/ha/task/FenceTask.java
@@ -0,0 +1,56 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ha.task;
+
+import org.apache.cloudstack.ha.HAConfig;
+import org.apache.cloudstack.ha.HAManager;
+import org.apache.cloudstack.ha.HAResource;
+import org.apache.cloudstack.ha.HAResourceCounter;
+import org.apache.cloudstack.ha.provider.HACheckerException;
+import org.apache.cloudstack.ha.provider.HAFenceException;
+import org.apache.cloudstack.ha.provider.HAProvider;
+
+import javax.inject.Inject;
+import java.util.concurrent.ExecutorService;
+
+public class FenceTask extends BaseHATask {
+
+ @Inject
+ private HAManager haManager;
+
+ public FenceTask(final HAResource resource, final HAProvider<HAResource> haProvider, final HAConfig haConfig,
+ final HAProvider.HAProviderConfig haProviderConfig, final ExecutorService executor) {
+ super(resource, haProvider, haConfig, haProviderConfig, executor);
+ }
+
+ public boolean performAction() throws HACheckerException, HAFenceException {
+ return getHaProvider().fence(getResource());
+ }
+
+ public void processResult(boolean result, Throwable e) {
+ final HAConfig haConfig = getHaConfig();
+ final HAResourceCounter counter = haManager.getHACounter(haConfig.getResourceId(), haConfig.getResourceType());
+ if (result) {
+ counter.resetRecoveryCounter();
+ haManager.transitionHAState(HAConfig.Event.Fenced, haConfig);
+ getHaProvider().fenceSubResources(getResource());
+ getHaProvider().enableMaintenance(getResource());
+ }
+ getHaProvider().sendAlert(getResource(), HAConfig.HAState.Fencing);
+ }
+}
diff --git a/server/src/org/apache/cloudstack/ha/task/HealthCheckTask.java b/server/src/org/apache/cloudstack/ha/task/HealthCheckTask.java
new file mode 100644
index 00000000000..92dcdc2164d
--- /dev/null
+++ b/server/src/org/apache/cloudstack/ha/task/HealthCheckTask.java
@@ -0,0 +1,63 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ha.task;
+
+import org.apache.cloudstack.ha.HAConfig;
+import org.apache.cloudstack.ha.HAManager;
+import org.apache.cloudstack.ha.HAResource;
+import org.apache.cloudstack.ha.HAResourceCounter;
+import org.apache.cloudstack.ha.provider.HACheckerException;
+import org.apache.cloudstack.ha.provider.HAProvider;
+import org.apache.log4j.Logger;
+
+import javax.inject.Inject;
+import java.util.concurrent.ExecutorService;
+
+public class HealthCheckTask extends BaseHATask {
+
+ @Inject
+ private HAManager haManager;
+
+ public static final Logger LOG = Logger.getLogger(HealthCheckTask.class);
+
+ public HealthCheckTask(final HAResource resource, final HAProvider<HAResource> haProvider, final HAConfig haConfig,
+ final HAProvider.HAProviderConfig haProviderConfig, final ExecutorService executor) {
+ super(resource, haProvider, haConfig, haProviderConfig, executor);
+ }
+
+ public boolean performAction() throws HACheckerException {
+ return getHaProvider().isHealthy(getResource());
+ }
+
+ public void processResult(boolean result, Throwable e) {
+ final HAConfig haConfig = getHaConfig();
+ final HAResourceCounter counter = haManager.getHACounter(haConfig.getResourceId(), haConfig.getResourceType());
+ if (result) {
+ haManager.transitionHAState(HAConfig.Event.HealthCheckPassed, haConfig);
+ if (haConfig.getState() == HAConfig.HAState.Fenced) {
+ haManager.disableHA(haConfig.getResourceId(), haConfig.getResourceType());
+ }
+ counter.resetSuspectTimestamp();
+ counter.resetActivityCounter();
+ counter.resetRecoveryCounter();
+ } else {
+ haManager.transitionHAState(HAConfig.Event.HealthCheckFailed, haConfig);
+ counter.markResourceSuspected();
+ }
+ }
+}
diff --git a/server/src/org/apache/cloudstack/ha/task/RecoveryTask.java b/server/src/org/apache/cloudstack/ha/task/RecoveryTask.java
new file mode 100644
index 00000000000..446dd5339ef
--- /dev/null
+++ b/server/src/org/apache/cloudstack/ha/task/RecoveryTask.java
@@ -0,0 +1,58 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.ha.task;
+
+import java.util.concurrent.ExecutorService;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.ha.HAConfig;
+import org.apache.cloudstack.ha.HAManager;
+import org.apache.cloudstack.ha.HAResource;
+import org.apache.cloudstack.ha.HAResourceCounter;
+import org.apache.cloudstack.ha.provider.HACheckerException;
+import org.apache.cloudstack.ha.provider.HAProvider;
+import org.apache.cloudstack.ha.provider.HARecoveryException;
+
+public class RecoveryTask extends BaseHATask {
+
+ @Inject
+ private HAManager haManager;
+
+ public RecoveryTask(final HAResource resource, final HAProvider<HAResource> haProvider, final HAConfig haConfig,
+ final HAProvider.HAProviderConfig haProviderConfig, final ExecutorService executor) {
+ super(resource, haProvider, haConfig, haProviderConfig, executor);
+ }
+
+ public boolean performAction() throws HACheckerException, HARecoveryException {
+ return getHaProvider().recover(getResource());
+ }
+
+ public void processResult(boolean result, Throwable e) {
+ final HAConfig haConfig = getHaConfig();
+ final HAResourceCounter counter = haManager.getHACounter(haConfig.getResourceId(), haConfig.getResourceType());
+ counter.incrRecoveryCounter();
+ counter.resetActivityCounter();
+
+ if (result) {
+ haManager.transitionHAState(HAConfig.Event.Recovered, haConfig);
+ getHaProvider().fenceSubResources(getResource());
+ }
+ getHaProvider().sendAlert(getResource(), HAConfig.HAState.Recovering);
+ }
+}
diff --git a/server/src/org/apache/cloudstack/network/ssl/CertServiceImpl.java b/server/src/org/apache/cloudstack/network/ssl/CertServiceImpl.java
index 9da9bddd5b8..e142ee5e339 100644
--- a/server/src/org/apache/cloudstack/network/ssl/CertServiceImpl.java
+++ b/server/src/org/apache/cloudstack/network/ssl/CertServiceImpl.java
@@ -123,6 +123,7 @@ public SslCertResponse uploadSslCert(final UploadSslCertCmd certCmd) {
final String key = certCmd.getKey();
final String password = certCmd.getPassword();
final String chain = certCmd.getChain();
+ final String name = certCmd.getName();
validate(cert, key, password, chain);
s_logger.debug("Certificate Validation succeeded");
@@ -142,7 +143,7 @@ public SslCertResponse uploadSslCert(final UploadSslCertCmd certCmd) {
final Long accountId = owner.getId();
final Long domainId = owner.getDomainId();
- final SslCertVO certVO = new SslCertVO(cert, key, password, chain, accountId, domainId, fingerPrint);
+ final SslCertVO certVO = new SslCertVO(cert, key, password, chain, accountId, domainId, fingerPrint, name);
_sslCertDao.persist(certVO);
return createCertResponse(certVO, null);
@@ -325,6 +326,7 @@ public SslCertResponse createCertResponse(final SslCertVO cert, final List<LoadB
response.setId(cert.getUuid());
response.setCertificate(cert.getCertificate());
response.setFingerprint(cert.getFingerPrint());
+ response.setName(cert.getName());
if (cert.getChain() != null) {
response.setCertchain(cert.getChain());
diff --git a/server/src/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementServiceImpl.java b/server/src/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementServiceImpl.java
index ca65ef7d192..7b09d297939 100644
--- a/server/src/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementServiceImpl.java
+++ b/server/src/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementServiceImpl.java
@@ -44,10 +44,13 @@
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
+import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.cloudstack.outofbandmanagement.dao.OutOfBandManagementDao;
import org.apache.cloudstack.outofbandmanagement.driver.OutOfBandManagementDriverChangePasswordCommand;
import org.apache.cloudstack.outofbandmanagement.driver.OutOfBandManagementDriverPowerCommand;
import org.apache.cloudstack.outofbandmanagement.driver.OutOfBandManagementDriverResponse;
+import org.apache.cloudstack.poll.BackgroundPollManager;
+import org.apache.cloudstack.poll.BackgroundPollTask;
import org.apache.cloudstack.utils.identity.ManagementServerNode;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@@ -78,6 +81,8 @@
private HostDao hostDao;
@Inject
private AlertManager alertMgr;
+ @Inject
+ private BackgroundPollManager backgroundPollManager;
private String name;
private long serviceId;
@@ -133,7 +138,7 @@ protected OutOfBandManagement updateConfig(final OutOfBandManagement outOfBandMa
outOfBandManagementConfig.setAddress(value);
break;
case PORT:
- outOfBandManagementConfig.setPort(Integer.parseInt(value));
+ outOfBandManagementConfig.setPort(value);
break;
case USERNAME:
outOfBandManagementConfig.setUsername(value);
@@ -161,9 +166,7 @@ protected OutOfBandManagement updateConfig(final OutOfBandManagement outOfBandMa
value = outOfBandManagementConfig.getAddress();
break;
case PORT:
- if (outOfBandManagementConfig.getPort() != null) {
- value = String.valueOf(outOfBandManagementConfig.getPort());
- }
+ value = outOfBandManagementConfig.getPort();
break;
case USERNAME:
value = outOfBandManagementConfig.getUsername();
@@ -202,12 +205,14 @@ private boolean transitionPowerState(OutOfBandManagement.PowerState.Event event,
OutOfBandManagement.PowerState currentPowerState = outOfBandManagementHost.getPowerState();
try {
OutOfBandManagement.PowerState newPowerState = OutOfBandManagement.PowerState.getStateMachine().getNextState(currentPowerState, event);
- boolean result = outOfBandManagementDao.updateState(currentPowerState, event, newPowerState, outOfBandManagementHost, null);
+ boolean result = OutOfBandManagement.PowerState.getStateMachine().transitTo(outOfBandManagementHost, event, null, outOfBandManagementDao);
if (result) {
final String message = String.format("Transitioned out-of-band management power state from:%s to:%s due to event:%s for the host id:%d", currentPowerState, newPowerState, event, outOfBandManagementHost.getHostId());
LOG.debug(message);
- ActionEventUtils.onActionEvent(CallContext.current().getCallingUserId(), CallContext.current().getCallingAccountId(), Domain.ROOT_DOMAIN,
- EventTypes.EVENT_HOST_OUTOFBAND_MANAGEMENT_POWERSTATE_TRANSITION, message);
+ if (newPowerState == OutOfBandManagement.PowerState.Unknown) {
+ ActionEventUtils.onActionEvent(CallContext.current().getCallingUserId(), CallContext.current().getCallingAccountId(), Domain.ROOT_DOMAIN,
+ EventTypes.EVENT_HOST_OUTOFBAND_MANAGEMENT_POWERSTATE_TRANSITION, message);
+ }
}
return result;
} catch (NoTransitionException ignored) {
@@ -262,7 +267,7 @@ private void checkOutOfBandManagementEnabledByZoneClusterHost(final Host host) {
}
public boolean isOutOfBandManagementEnabled(final Host host) {
- return isOutOfBandManagementEnabledForZone(host.getDataCenterId())
+ return host != null && isOutOfBandManagementEnabledForZone(host.getDataCenterId())
&& isOutOfBandManagementEnabledForCluster(host.getClusterId())
&& isOutOfBandManagementEnabledForHost(host.getId());
}
@@ -278,7 +283,7 @@ public boolean transitionPowerStateToDisabled(List<? extends Host> hosts) {
public void submitBackgroundPowerSyncTask(final Host host) {
if (host != null) {
- backgroundSyncBlockingExecutor.submit(new OutOfBandManagementBackgroundTask(this, host, OutOfBandManagement.PowerOperation.STATUS));
+ backgroundSyncBlockingExecutor.submit(new PowerOperationTask(this, host, OutOfBandManagement.PowerOperation.STATUS));
}
}
@@ -356,7 +361,7 @@ public OutOfBandManagementResponse disableOutOfBandManagement(final Host host) {
@Override
@ActionEvent(eventType = EventTypes.EVENT_HOST_OUTOFBAND_MANAGEMENT_CONFIGURE, eventDescription = "updating out-of-band management configuration")
- public OutOfBandManagementResponse configureOutOfBandManagement(final Host host, final ImmutableMap<OutOfBandManagement.Option, String> options) {
+ public OutOfBandManagementResponse configure(final Host host, final ImmutableMap<OutOfBandManagement.Option, String> options) {
OutOfBandManagement outOfBandManagementConfig = outOfBandManagementDao.findByHost(host.getId());
if (outOfBandManagementConfig == null) {
outOfBandManagementConfig = outOfBandManagementDao.persist(new OutOfBandManagementVO(host.getId()));
@@ -384,7 +389,7 @@ public OutOfBandManagementResponse configureOutOfBandManagement(final Host host,
@Override
@ActionEvent(eventType = EventTypes.EVENT_HOST_OUTOFBAND_MANAGEMENT_ACTION, eventDescription = "issuing host out-of-band management action", async = true)
- public OutOfBandManagementResponse executeOutOfBandManagementPowerOperation(final Host host, final OutOfBandManagement.PowerOperation powerOperation, final Long timeout) {
+ public OutOfBandManagementResponse executePowerOperation(final Host host, final OutOfBandManagement.PowerOperation powerOperation, final Long timeout) {
checkOutOfBandManagementEnabledByZoneClusterHost(host);
final OutOfBandManagement outOfBandManagementConfig = getConfigForHost(host);
final ImmutableMap<OutOfBandManagement.Option, String> options = getOptions(outOfBandManagementConfig);
@@ -428,7 +433,7 @@ public OutOfBandManagementResponse executeOutOfBandManagementPowerOperation(fina
@Override
@ActionEvent(eventType = EventTypes.EVENT_HOST_OUTOFBAND_MANAGEMENT_CHANGE_PASSWORD, eventDescription = "updating out-of-band management password")
- public OutOfBandManagementResponse changeOutOfBandManagementPassword(final Host host, final String newPassword) {
+ public OutOfBandManagementResponse changePassword(final Host host, final String newPassword) {
checkOutOfBandManagementEnabledByZoneClusterHost(host);
if (Strings.isNullOrEmpty(newPassword)) {
throw new CloudRuntimeException(String.format("Cannot change out-of-band management password as provided new-password is null or empty for the host %s.", host.getUuid()));
@@ -503,7 +508,9 @@ public boolean configure(final String name, final Map<String, Object> params) th
0L, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10 * poolSize, true), new ThreadPoolExecutor.CallerRunsPolicy());
- LOG.info("Starting out-of-band management background sync executor with thread pool-size=" + poolSize + " and background sync thread interval=" + SyncThreadInterval.value() + "s");
+ backgroundPollManager.submitTask(new OutOfBandManagementPowerStatePollTask());
+
+ LOG.info("Starting out-of-band management background sync executor with thread pool-size=" + poolSize);
return true;
}
@@ -516,7 +523,7 @@ public boolean start() {
@Override
public boolean stop() {
backgroundSyncBlockingExecutor.shutdown();
- outOfBandManagementDao.expireOutOfBandManagementOwnershipByServer(getId());
+ outOfBandManagementDao.expireServerOwnership(getId());
return true;
}
@@ -527,7 +534,7 @@ public String getConfigComponentName() {
@Override
public ConfigKey<?>[] getConfigKeys() {
- return new ConfigKey<?>[] {ActionTimeout, SyncThreadInterval, SyncThreadPoolSize};
+ return new ConfigKey<?>[] {ActionTimeout, SyncThreadPoolSize};
}
public List<OutOfBandManagementDriver> getOutOfBandManagementDrivers() {
@@ -537,4 +544,42 @@ public String getConfigComponentName() {
public void setOutOfBandManagementDrivers(List<OutOfBandManagementDriver> outOfBandManagementDrivers) {
this.outOfBandManagementDrivers = outOfBandManagementDrivers;
}
+
+ private final class OutOfBandManagementPowerStatePollTask extends ManagedContextRunnable implements BackgroundPollTask {
+ @Override
+ protected void runInContext() {
+ try {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Host out-of-band management power state poll task is running...");
+ }
+ final List<OutOfBandManagementVO> outOfBandManagementHosts = outOfBandManagementDao.findAllByManagementServer(ManagementServerNode.getManagementServerId());
+ if (outOfBandManagementHosts == null || outOfBandManagementHosts.isEmpty()) {
+ return;
+ }
+ for (final OutOfBandManagement outOfBandManagementHost : outOfBandManagementHosts) {
+ final Host host = hostDao.findById(outOfBandManagementHost.getHostId());
+ if (host == null) {
+ continue;
+ }
+ if (isOutOfBandManagementEnabled(host)) {
+ submitBackgroundPowerSyncTask(host);
+ } else if (outOfBandManagementHost.getPowerState() != OutOfBandManagement.PowerState.Disabled) {
+ if (transitionPowerStateToDisabled(Collections.singletonList(host))) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Out-of-band management was disabled in zone/cluster/host, disabled power state for host id:" + host.getId());
+ }
+ }
+ }
+ }
+ } catch (Throwable t) {
+ LOG.error("Error trying to retrieve host out-of-band management stats", t);
+ }
+ }
+
+ @Override
+ public Long getDelay() {
+ return null;
+ }
+
+ }
}
diff --git a/server/src/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementBackgroundTask.java b/server/src/org/apache/cloudstack/outofbandmanagement/PowerOperationTask.java
similarity index 80%
rename from server/src/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementBackgroundTask.java
rename to server/src/org/apache/cloudstack/outofbandmanagement/PowerOperationTask.java
index 38e139ec610..9c346d76c5f 100644
--- a/server/src/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementBackgroundTask.java
+++ b/server/src/org/apache/cloudstack/outofbandmanagement/PowerOperationTask.java
@@ -20,14 +20,14 @@
import com.cloud.host.Host;
import org.apache.log4j.Logger;
-public class OutOfBandManagementBackgroundTask implements Runnable {
- public static final Logger LOG = Logger.getLogger(OutOfBandManagementBackgroundTask.class);
+public class PowerOperationTask implements Runnable {
+ public static final Logger LOG = Logger.getLogger(PowerOperationTask.class);
final private OutOfBandManagementService service;
final private Host host;
final private OutOfBandManagement.PowerOperation powerOperation;
- public OutOfBandManagementBackgroundTask(OutOfBandManagementService service, Host host, OutOfBandManagement.PowerOperation powerOperation) {
+ public PowerOperationTask(OutOfBandManagementService service, Host host, OutOfBandManagement.PowerOperation powerOperation) {
this.service = service;
this.host = host;
this.powerOperation = powerOperation;
@@ -41,7 +41,7 @@ public String toString() {
@Override
public void run() {
try {
- service.executeOutOfBandManagementPowerOperation(host, powerOperation, null);
+ service.executePowerOperation(host, powerOperation, null);
} catch (Exception e) {
LOG.warn(String.format("Out-of-band management background task operation=%s for host id=%d failed with: %s",
powerOperation.name(), host.getId(), e.getMessage()));
diff --git a/server/src/org/apache/cloudstack/poll/BackgroundPollManagerImpl.java b/server/src/org/apache/cloudstack/poll/BackgroundPollManagerImpl.java
new file mode 100644
index 00000000000..f4a634032d4
--- /dev/null
+++ b/server/src/org/apache/cloudstack/poll/BackgroundPollManagerImpl.java
@@ -0,0 +1,83 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.poll;
+
+import com.cloud.utils.component.Manager;
+import com.cloud.utils.component.ManagerBase;
+import com.cloud.utils.concurrency.NamedThreadFactory;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.google.common.base.Preconditions;
+import org.apache.log4j.Logger;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+public final class BackgroundPollManagerImpl extends ManagerBase implements BackgroundPollManager, Manager {
+ public static final Logger LOG = Logger.getLogger(BackgroundPollManagerImpl.class);
+
+ private ScheduledExecutorService backgroundPollTaskScheduler;
+ private List<BackgroundPollTask> submittedTasks = new ArrayList<>();
+ private volatile boolean isConfiguredAndStarted = false;
+
+ public long getInitialDelay() {
+ return 5000L;
+ }
+
+ public long getRoundDelay() {
+ return 4000L;
+ }
+
+ @Override
+ public boolean start() {
+ if (isConfiguredAndStarted) {
+ return true;
+ }
+ backgroundPollTaskScheduler = Executors.newScheduledThreadPool(submittedTasks.size() + 1, new NamedThreadFactory("BackgroundTaskPollManager"));
+ for (final BackgroundPollTask task : submittedTasks) {
+ Long delay = task.getDelay();
+ if (delay == null) {
+ delay = getRoundDelay();
+ }
+ backgroundPollTaskScheduler.scheduleWithFixedDelay(task, getInitialDelay(), delay, TimeUnit.MILLISECONDS);
+ LOG.debug("Scheduled background poll task: " + task.getClass().getName());
+ }
+ isConfiguredAndStarted = true;
+ return true;
+ }
+
+ @Override
+ public boolean stop() {
+ if (isConfiguredAndStarted) {
+ backgroundPollTaskScheduler.shutdown();
+ }
+ return true;
+ }
+
+ @Override
+ public void submitTask(final BackgroundPollTask task) {
+ Preconditions.checkNotNull(task);
+ if (isConfiguredAndStarted) {
+ throw new CloudRuntimeException("Background Poll Manager cannot accept poll task as it has been configured and started.");
+ }
+ LOG.debug("Background Poll Manager received task: " + task.getClass().getSimpleName());
+ submittedTasks.add(task);
+ }
+}
diff --git a/server/src/org/cloud/network/router/deployment/VpcRouterDeploymentDefinition.java b/server/src/org/cloud/network/router/deployment/VpcRouterDeploymentDefinition.java
index 26f2379804e..8ccecce619a 100644
--- a/server/src/org/cloud/network/router/deployment/VpcRouterDeploymentDefinition.java
+++ b/server/src/org/cloud/network/router/deployment/VpcRouterDeploymentDefinition.java
@@ -72,11 +72,6 @@ public boolean isVpcRouter() {
return true;
}
- @Override
- public boolean isPublicNetwork() {
- return true;
- }
-
@Override
protected void lock() {
final Vpc vpcLock = vpcDao.acquireInLockTable(vpc.getId());
@@ -115,12 +110,19 @@ protected void checkPreconditions() {
*/
@Override
protected boolean prepareDeployment() {
+ //Check if the VR is the src NAT provider...
+ isPublicNetwork = vpcMgr.isSrcNatIpRequired(vpc.getVpcOfferingId());
+
+ // Check if public network has to be set on VR
return true;
}
@Override
protected void findSourceNatIP() throws InsufficientAddressCapacityException, ConcurrentOperationException {
- sourceNatIp = vpcMgr.assignSourceNatIpAddressToVpc(owner, vpc);
+ sourceNatIp = null;
+ if (isPublicNetwork) {
+ sourceNatIp = vpcMgr.assignSourceNatIpAddressToVpc(owner, vpc);
+ }
}
@Override
diff --git a/server/test/com/cloud/configuration/ConfigurationManagerTest.java b/server/test/com/cloud/configuration/ConfigurationManagerTest.java
index 34f91c4e27c..80c184b0bf9 100644
--- a/server/test/com/cloud/configuration/ConfigurationManagerTest.java
+++ b/server/test/com/cloud/configuration/ConfigurationManagerTest.java
@@ -17,40 +17,34 @@
package com.cloud.configuration;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
import java.lang.reflect.Field;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
-import com.cloud.user.User;
-import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
-import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
-import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
import org.apache.log4j.Logger;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+
import org.apache.cloudstack.api.command.admin.vlan.DedicatePublicIpRangeCmd;
import org.apache.cloudstack.api.command.admin.vlan.ReleasePublicIpRangeCmd;
+import org.apache.cloudstack.api.command.user.network.ListNetworkOfferingsCmd;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
+import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
+import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.dc.AccountVlanMapVO;
@@ -72,13 +66,17 @@
import com.cloud.host.dao.HostDao;
import com.cloud.network.IpAddressManager;
import com.cloud.network.Network;
-import com.cloud.network.NetworkModel;
import com.cloud.network.Network.Capability;
+import com.cloud.network.NetworkModel;
+import com.cloud.network.Networks;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.PhysicalNetworkVO;
+import com.cloud.offering.NetworkOffering;
+import com.cloud.offerings.NetworkOfferingVO;
+import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.projects.ProjectManager;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.VolumeDao;
@@ -86,18 +84,34 @@
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.ResourceLimitService;
+import com.cloud.user.User;
import com.cloud.user.UserVO;
import com.cloud.user.dao.AccountDao;
+import com.cloud.utils.db.Filter;
+import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.TransactionLegacy;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.Ip;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.dao.VMInstanceDao;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
public class ConfigurationManagerTest {
private static final Logger s_logger = Logger.getLogger(ConfigurationManagerTest.class);
+ @InjectMocks
ConfigurationManagerImpl configurationMgr = new ConfigurationManagerImpl();
DedicatePublicIpRangeCmd dedicatePublicIpRangesCmd = new DedicatePublicIpRangeCmdExtn();
@@ -115,6 +129,8 @@
@Mock
NetworkOrchestrationService _networkMgr;
@Mock
+ NetworkOfferingDao _networkOfferingDao;
+ @Mock
AccountDao _accountDao;
@Mock
VlanDao _vlanDao;
@@ -148,6 +164,8 @@
PhysicalNetworkDao _physicalNetworkDao;
@Mock
ImageStoreDao _imageStoreDao;
+ @Mock
+ ConfigurationDao _configDao;
VlanVO vlan = new VlanVO(Vlan.VlanType.VirtualNetwork, "vlantag", "vlangateway", "vlannetmask", 1L, "iprange", 1L, 1L, null, null, null);
@@ -159,28 +177,6 @@
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
- configurationMgr._accountMgr = _accountMgr;
- configurationMgr._projectMgr = _projectMgr;
- configurationMgr._resourceLimitMgr = _resourceLimitMgr;
- configurationMgr._networkMgr = _networkMgr;
- configurationMgr._accountDao = _accountDao;
- configurationMgr._vlanDao = _vlanDao;
- configurationMgr._accountVlanMapDao = _accountVlanMapDao;
- configurationMgr._domainVlanMapDao = _domainVlanMapDao;
- configurationMgr._publicIpAddressDao = _publicIpAddressDao;
- configurationMgr._zoneDao = _zoneDao;
- configurationMgr._firewallDao = _firewallDao;
- configurationMgr._ipAddrMgr = _ipAddrMgr;
- configurationMgr._networkModel = _networkModel;
- configurationMgr._privateIpAddressDao = _privateIpAddressDao;
- configurationMgr._volumeDao = _volumeDao;
- configurationMgr._hostDao = _hostDao;
- configurationMgr._vmInstanceDao = _vmInstanceDao;
- configurationMgr._clusterDao = _clusterDao;
- configurationMgr._podDao = _podDao;
- configurationMgr._physicalNetworkDao = _physicalNetworkDao;
- configurationMgr._imageStoreDao = _imageStoreDao;
-
Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString());
when(configurationMgr._accountMgr.getAccount(anyLong())).thenReturn(account);
@@ -492,6 +488,40 @@ void runReleaseNonDedicatedPublicIpRange() throws Exception {
}
}
+ @Test
+ public void searchForNetworkOfferingsTest() {
+
+ final NetworkOfferingVO off1 = new NetworkOfferingVO("off1", "off1", Networks.TrafficType.Guest, false, false, null, null, false,
+ NetworkOffering.Availability.Optional, null, Network.GuestType.Isolated, true, false, false, false,
+ false);
+ final NetworkOfferingVO off2 = new NetworkOfferingVO("off2", "off2", Networks.TrafficType.Guest, false, false, null, null, false,
+ NetworkOffering.Availability.Optional, null, Network.GuestType.Isolated, true, false, false, false,
+ false);
+ final NetworkOfferingVO off3 = new NetworkOfferingVO("off3", "off3", Networks.TrafficType.Guest, false, false, null, null, false,
+ NetworkOffering.Availability.Optional, null, Network.GuestType.Isolated, true, false, false, false,
+ false);
+ List<NetworkOfferingVO> offerings = Arrays.asList(
+ off1,
+ off2,
+ off3
+ );
+
+ Mockito.when(_networkOfferingDao.createSearchCriteria()).thenReturn(Mockito.mock(SearchCriteria.class));
+ Mockito.when(_networkOfferingDao.search(Mockito.any(SearchCriteria.class), Mockito.any(Filter.class))).thenReturn(offerings);
+
+ ListNetworkOfferingsCmd cmd = Mockito.spy(ListNetworkOfferingsCmd.class);
+ Mockito.when(cmd.getPageSize()).thenReturn(10);
+
+ assertThat(configurationMgr.searchForNetworkOfferings(cmd).second(), is(3));
+
+ ConfigurationManagerImpl spy = Mockito.spy(configurationMgr);
+ Mockito.doReturn(false).when(spy).isOfferingForVpc(off1);
+ Mockito.doReturn(false).when(spy).isOfferingForVpc(off2);
+ Mockito.doReturn(true).when(spy).isOfferingForVpc(off3);
+ Mockito.when(cmd.getForVpc()).thenReturn(Boolean.FALSE);
+ assertThat(spy.searchForNetworkOfferings(cmd).second(), is(2));
+ }
+
@Test
public void validateEmptyStaticNatServiceCapablitiesTest() {
Map<Capability, String> staticNatServiceCapabilityMap = new HashMap<Capability, String>();
diff --git a/server/test/com/cloud/network/CreatePrivateNetworkTest.java b/server/test/com/cloud/network/CreatePrivateNetworkTest.java
index 8a7b54cb20f..178ed84d748 100644
--- a/server/test/com/cloud/network/CreatePrivateNetworkTest.java
+++ b/server/test/com/cloud/network/CreatePrivateNetworkTest.java
@@ -121,7 +121,7 @@ public void setup() throws Exception {
new NetworkVO(1L, TrafficType.Guest, Mode.None, BroadcastDomainType.Vlan, 1L, 1L, 1L, 1L, "bla", "fake", "eet.net", GuestType.Isolated, 1L, 1L,
ACLType.Account, false, 1L, false);
when(
- networkService._networkMgr.createGuestNetwork(eq(ntwkOff.getId()), eq("bla"), eq("fake"), eq("10.1.1.1"), eq("10.1.1.0/24"), anyString(), anyString(),
+ networkService._networkMgr.createGuestNetwork(eq(ntwkOff.getId()), eq("bla"), eq("fake"), eq("10.1.1.1"), eq("10.1.1.0/24"), anyString(), anyBoolean(), anyString(),
eq(account), anyLong(), eq(physicalNetwork), eq(physicalNetwork.getDataCenterId()), eq(ACLType.Account), anyBoolean(), eq(1L), anyString(), anyString(),
anyBoolean(), anyString())).thenReturn(net);
diff --git a/server/test/com/cloud/network/ExternalLoadBalancerDeviceManagerImplTest.java b/server/test/com/cloud/network/ExternalLoadBalancerDeviceManagerImplTest.java
index dbc31ba6ef4..47c3250bcaa 100644
--- a/server/test/com/cloud/network/ExternalLoadBalancerDeviceManagerImplTest.java
+++ b/server/test/com/cloud/network/ExternalLoadBalancerDeviceManagerImplTest.java
@@ -61,16 +61,21 @@
import com.cloud.network.dao.NetworkServiceMapDao;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
+import com.cloud.network.dao.VirtualRouterProviderDao;
import com.cloud.network.lb.LoadBalancingRule;
import com.cloud.network.rules.dao.PortForwardingRulesDao;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.resource.ResourceManager;
+import com.cloud.service.dao.ServiceOfferingDao;
+import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.user.AccountManager;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserStatisticsDao;
import com.cloud.utils.net.Ip;
+import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.NicDao;
+import com.cloud.vm.dao.VMInstanceDao;
@RunWith(MockitoJUnitRunner.class)
public class ExternalLoadBalancerDeviceManagerImplTest {
@@ -135,9 +140,20 @@
protected HostPodDao _podDao = null;
@Mock
IpAddressManager _ipAddrMgr;
-
+ @Mock
+ protected VirtualMachineManager _itMgr;
@Mock
Network network;
+ @Mock
+ VMInstanceDao _vmDao;
+ @Mock
+ VMTemplateDao _templateDao;
+ @Mock
+ ServiceOfferingDao _serviceOfferingDao;
+ @Mock
+ PhysicalNetworkServiceProviderDao _physicalProviderDao;
+ @Mock
+ VirtualRouterProviderDao _vrProviderDao;
@Mock
LoadBalancingRule rule;
@@ -192,6 +208,7 @@ public void getLBHealthChecksNullAnswer() throws ResourceUnavailableException,
private void setupLBHealthChecksMocks() throws URISyntaxException {
Mockito.when(network.getId()).thenReturn(42l);
+ Mockito.when(network.getNetworkOfferingId()).thenReturn(1l);
Mockito.when(network.getBroadcastUri()).thenReturn(new URI("vlan://1"));
NetworkExternalLoadBalancerVO externalLb = Mockito
.mock(NetworkExternalLoadBalancerVO.class);
diff --git a/server/test/com/cloud/network/MockNetworkModelImpl.java b/server/test/com/cloud/network/MockNetworkModelImpl.java
index f3d1f3827bd..3c3fd7097cd 100644
--- a/server/test/com/cloud/network/MockNetworkModelImpl.java
+++ b/server/test/com/cloud/network/MockNetworkModelImpl.java
@@ -30,6 +30,7 @@
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.GuestType;
+import com.cloud.network.Network.IpAddresses;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.Networks.IsolationType;
@@ -830,7 +831,7 @@ public void checkIp6Parameters(String startIPv6, String endIPv6, String ip6Gatew
}
@Override
- public void checkRequestedIpAddresses(long networkId, String ip4, String ip6) throws InvalidParameterValueException {
+ public void checkRequestedIpAddresses(long networkId, IpAddresses ips) throws InvalidParameterValueException {
// TODO Auto-generated method stub
}
@@ -901,4 +902,9 @@ public boolean getNetworkEgressDefaultPolicy(Long networkId) {
return null;
}
+ @Override
+ public String getValidNetworkCidr(Network guestNetwork) {
+ return null;
+ }
+
}
diff --git a/server/test/com/cloud/resource/MockResourceManagerImpl.java b/server/test/com/cloud/resource/MockResourceManagerImpl.java
index e293f2d5400..3eb5f519e64 100755
--- a/server/test/com/cloud/resource/MockResourceManagerImpl.java
+++ b/server/test/com/cloud/resource/MockResourceManagerImpl.java
@@ -364,6 +364,11 @@ public boolean deleteHost(final long hostId, final boolean isForced, final boole
return null;
}
+ @Override
+ public List<HostVO> listAllUpHosts(Type type, Long clusterId, Long podId, long dcId) {
+ return null;
+ }
+
/* (non-Javadoc)
* @see com.cloud.resource.ResourceManager#listAllHostsInCluster(long)
*/
diff --git a/server/test/com/cloud/server/ConfigurationServerImplTest.java b/server/test/com/cloud/server/ConfigurationServerImplTest.java
index b64f3f72aa2..8b0af999011 100644
--- a/server/test/com/cloud/server/ConfigurationServerImplTest.java
+++ b/server/test/com/cloud/server/ConfigurationServerImplTest.java
@@ -16,8 +16,17 @@
// under the License.
package com.cloud.server;
-import java.io.File;
-import java.io.IOException;
+import org.apache.cloudstack.framework.config.ConfigDepot;
+import org.apache.cloudstack.framework.config.ConfigDepotAdmin;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+import org.mockito.runners.MockitoJUnitRunner;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.dao.ResourceCountDao;
@@ -32,19 +41,6 @@
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.db.TransactionLegacy;
-import org.apache.cloudstack.framework.config.ConfigDepot;
-import org.apache.cloudstack.framework.config.ConfigDepotAdmin;
-import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
-import org.apache.commons.codec.binary.Base64;
-import org.apache.commons.io.FileUtils;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.Spy;
-import org.mockito.runners.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class ConfigurationServerImplTest {
@@ -101,41 +97,6 @@ protected boolean isOnWindows() {
}
};
- final static String TEST = "the quick brown fox jumped over the lazy dog";
-
- @Test(expected = IOException.class)
- public void testGetBase64KeystoreNoSuchFile() throws IOException {
- ConfigurationServerImpl.getBase64Keystore("notexisting" + System.currentTimeMillis());
- }
-
- @Test(expected = IOException.class)
- public void testGetBase64KeystoreTooBigFile() throws IOException {
- File temp = File.createTempFile("keystore", "");
- StringBuilder builder = new StringBuilder();
- for (int i = 0; i < 1000; i++) {
- builder.append("way too long...\n");
- }
- FileUtils.writeStringToFile(temp, builder.toString());
- try {
- ConfigurationServerImpl.getBase64Keystore(temp.getPath());
- } finally {
- temp.delete();
- }
- }
-
- @Test
- public void testGetBase64Keystore() throws IOException {
- File temp = File.createTempFile("keystore", "");
- try {
- FileUtils.writeStringToFile(temp, Base64.encodeBase64String(TEST.getBytes()));
- final String keystore = ConfigurationServerImpl.getBase64Keystore(temp.getPath());
- // let's decode it to make sure it makes sense
- Base64.decodeBase64(keystore);
- } finally {
- temp.delete();
- }
- }
-
@Test
public void testWindowsScript() {
Assert.assertTrue(windowsImpl.isOnWindows());
diff --git a/server/test/com/cloud/servlet/StaticResourceServletTest.java b/server/test/com/cloud/servlet/StaticResourceServletTest.java
deleted file mode 100644
index ae5c3847f5b..00000000000
--- a/server/test/com/cloud/servlet/StaticResourceServletTest.java
+++ /dev/null
@@ -1,235 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-package com.cloud.servlet;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.io.FileUtils;
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Matchers;
-import org.mockito.Mockito;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-public class StaticResourceServletTest {
-
- File rootDirectory;
-
- @Before
- public void setupFiles() throws IOException {
- rootDirectory = new File("target/tmp");
- rootDirectory.mkdirs();
- final File webInf = new File(rootDirectory, "WEB-INF");
- webInf.mkdirs();
- final File dir = new File(rootDirectory, "dir");
- dir.mkdirs();
- final File indexHtml = new File(rootDirectory, "index.html");
- indexHtml.createNewFile();
- FileUtils.writeStringToFile(indexHtml, "index.html");
- final File defaultCss = new File(rootDirectory, "default.css");
- defaultCss.createNewFile();
- final File defaultCssGziped = new File(rootDirectory, "default.css.gz");
- defaultCssGziped.createNewFile();
- }
-
- @After
- public void cleanupFiles() {
- FileUtils.deleteQuietly(rootDirectory);
- }
-
- // negative tests
-
- @Test
- public void testNoSuchFile() throws ServletException, IOException {
- final StaticResourceServlet servlet = Mockito
- .mock(StaticResourceServlet.class);
- Mockito.doCallRealMethod()
- .when(servlet)
- .doGet(Matchers.any(HttpServletRequest.class),
- Matchers.any(HttpServletResponse.class));
- final ServletContext servletContext = Mockito
- .mock(ServletContext.class);
- Mockito.when(servletContext.getRealPath("notexisting.css")).thenReturn(
- new File(rootDirectory, "notexisting.css").getAbsolutePath());
- Mockito.when(servlet.getServletContext()).thenReturn(servletContext);
-
- final HttpServletRequest request = Mockito
- .mock(HttpServletRequest.class);
- Mockito.when(request.getServletPath()).thenReturn("notexisting.css");
- final HttpServletResponse response = Mockito
- .mock(HttpServletResponse.class);
- servlet.doGet(request, response);
- Mockito.verify(response).setStatus(HttpServletResponse.SC_NOT_FOUND);
- }
-
- @Test
- public void testDirectory() throws ServletException, IOException {
- final HttpServletResponse response = doGetTest("dir");
- Mockito.verify(response).setStatus(HttpServletResponse.SC_NOT_FOUND);
- }
-
- @Test
- public void testWebInf() throws ServletException, IOException {
- final HttpServletResponse response = doGetTest("WEB-INF/web.xml");
- Mockito.verify(response).setStatus(HttpServletResponse.SC_NOT_FOUND);
- }
-
- // positive tests
-
- @Test
- public void testNotCompressedFile() throws ServletException, IOException {
- final HttpServletResponse response = doGetTest("index.html");
- Mockito.verify(response).setStatus(HttpServletResponse.SC_OK);
- Mockito.verify(response).setContentType("text/html");
- Mockito.verify(response, Mockito.times(0)).setHeader(
- "Content-Encoding", "gzip");
- }
-
- @Test
- public void testCompressedFile() throws ServletException, IOException {
- final HashMap<String, String> headers = new HashMap<String, String>();
- headers.put("Accept-Encoding", "gzip");
- final HttpServletResponse response = doGetTest("default.css", headers);
- Mockito.verify(response).setStatus(HttpServletResponse.SC_OK);
- Mockito.verify(response).setContentType("text/css");
- Mockito.verify(response, Mockito.times(1)).setHeader(
- "Content-Encoding", "gzip");
- }
-
- @Test
- public void testCompressedFileWithoutBrowserSupport()
- throws ServletException, IOException {
- final HashMap<String, String> headers = new HashMap<String, String>();
- headers.put("Accept-Encoding", "");
- final HttpServletResponse response = doGetTest("default.css", headers);
- Mockito.verify(response).setStatus(HttpServletResponse.SC_OK);
- Mockito.verify(response).setContentType("text/css");
- Mockito.verify(response, Mockito.times(0)).setHeader(
- "Content-Encoding", "gzip");
- }
-
- @Test
- public void testWithEtag() throws ServletException, IOException {
- final HashMap<String, String> headers = new HashMap<String, String>();
- headers.put("If-None-Match", StaticResourceServlet.getEtag(new File(
- rootDirectory, "default.css")));
- final HttpServletResponse response = doGetTest("default.css", headers);
- Mockito.verify(response).setStatus(HttpServletResponse.SC_NOT_MODIFIED);
- }
-
- @Test
- public void testWithEtagOutdated() throws ServletException, IOException {
- final HashMap<String, String> headers = new HashMap<String, String>();
- headers.put("If-None-Match", "NO-GOOD-ETAG");
- final HttpServletResponse response = doGetTest("default.css", headers);
- Mockito.verify(response).setStatus(HttpServletResponse.SC_OK);
- }
-
- // utility methods
-
- @Test
- public void getEtag() {
- Assert.assertNotNull(StaticResourceServlet.getEtag(new File(
- rootDirectory, "index.html")));
- }
-
- @Test
- public void getContentType() {
- Assert.assertEquals("text/plain",
- StaticResourceServlet.getContentType("foo.txt"));
- Assert.assertEquals("text/html",
- StaticResourceServlet.getContentType("index.html"));
- Assert.assertEquals("text/plain",
- StaticResourceServlet.getContentType("README.TXT"));
- }
-
- @Test
- public void isClientCompressionSupported() {
- final HttpServletRequest request = Mockito
- .mock(HttpServletRequest.class);
- Mockito.when(request.getHeader("Accept-Encoding")).thenReturn(
- "gzip, deflate");
- Assert.assertTrue(StaticResourceServlet
- .isClientCompressionSupported(request));
- }
-
- @Test
- public void isClientCompressionSupportedWithoutHeader() {
- final HttpServletRequest request = Mockito
- .mock(HttpServletRequest.class);
- Mockito.when(request.getHeader("Accept-Encoding")).thenReturn(null);
- Assert.assertFalse(StaticResourceServlet
- .isClientCompressionSupported(request));
- }
-
- // test utilities
- private HttpServletResponse doGetTest(final String uri)
- throws ServletException, IOException {
- return doGetTest(uri, Collections.<String, String> emptyMap());
- }
-
- private HttpServletResponse doGetTest(final String uri,
- final Map<String, String> headers) throws ServletException,
- IOException {
- final StaticResourceServlet servlet = Mockito
- .mock(StaticResourceServlet.class);
- Mockito.doCallRealMethod()
- .when(servlet)
- .doGet(Matchers.any(HttpServletRequest.class),
- Matchers.any(HttpServletResponse.class));
- final ServletContext servletContext = Mockito
- .mock(ServletContext.class);
- Mockito.when(servletContext.getRealPath(uri)).thenReturn(
- new File(rootDirectory, uri).getAbsolutePath());
- Mockito.when(servlet.getServletContext()).thenReturn(servletContext);
-
- final HttpServletRequest request = Mockito
- .mock(HttpServletRequest.class);
- Mockito.when(request.getServletPath()).thenReturn(uri);
- Mockito.when(request.getHeader(Matchers.anyString())).thenAnswer(
- new Answer<String>() {
-
- @Override
- public String answer(final InvocationOnMock invocation)
- throws Throwable {
- return headers.get(invocation.getArguments()[0]);
- }
- });
- final HttpServletResponse response = Mockito
- .mock(HttpServletResponse.class);
- final ServletOutputStream responseBody = Mockito
- .mock(ServletOutputStream.class);
- Mockito.when(response.getOutputStream()).thenReturn(responseBody);
- servlet.doGet(request, response);
- return response;
- }
-
-}
diff --git a/server/test/com/cloud/storage/VolumeApiServiceImplTest.java b/server/test/com/cloud/storage/VolumeApiServiceImplTest.java
index 35df0db89a3..16f39bcddff 100644
--- a/server/test/com/cloud/storage/VolumeApiServiceImplTest.java
+++ b/server/test/com/cloud/storage/VolumeApiServiceImplTest.java
@@ -386,7 +386,7 @@ public void testTakeSnapshotF1() throws ResourceAllocationException {
when(_volFactory.getVolume(anyLong())).thenReturn(volumeInfoMock);
when(volumeInfoMock.getState()).thenReturn(Volume.State.Allocated);
when(volumeInfoMock.getPoolId()).thenReturn(1L);
- _svc.takeSnapshot(5L, Snapshot.MANUAL_POLICY_ID, 3L, null, false, null);
+ _svc.takeSnapshot(5L, Snapshot.MANUAL_POLICY_ID, 3L, null, false, null, false);
}
@Test
@@ -396,7 +396,7 @@ public void testTakeSnapshotF2() throws ResourceAllocationException {
when(volumeInfoMock.getInstanceId()).thenReturn(null);
when(volumeInfoMock.getPoolId()).thenReturn(1L);
when (volService.takeSnapshot(Mockito.any(VolumeInfo.class))).thenReturn(snapshotInfoMock);
- _svc.takeSnapshot(5L, Snapshot.MANUAL_POLICY_ID, 3L, null, false, null);
+ _svc.takeSnapshot(5L, Snapshot.MANUAL_POLICY_ID, 3L, null, false, null, false);
}
@Test
diff --git a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java
index bcee896ca30..9ac0648a533 100644
--- a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java
+++ b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java
@@ -440,7 +440,7 @@ public NetworkOfferingVO createNetworkOffering(String name, String displayText,
*/
@Override
public Vlan createVlanAndPublicIpRange(long zoneId, long networkId, long physicalNetworkId, boolean forVirtualNetwork, Long podId, String startIP, String endIP,
- String vlanGateway, String vlanNetmask, String vlanId, Domain domain, Account vlanOwner, String startIPv6, String endIPv6, String vlanGatewayv6, String vlanCidrv6)
+ String vlanGateway, String vlanNetmask, String vlanId, boolean bypassVlanOverlapCheck, Domain domain, Account vlanOwner, String startIPv6, String endIPv6, String vlanGatewayv6, String vlanCidrv6)
throws InsufficientCapacityException, ConcurrentOperationException, InvalidParameterValueException {
// TODO Auto-generated method stub
return null;
diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
index d61378b3fdf..9b895c25541 100644
--- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
+++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
@@ -25,6 +25,7 @@
import javax.naming.ConfigurationException;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
+import org.apache.cloudstack.api.command.admin.address.ReleasePodIpCmdByAdmin;
import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd;
import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd;
import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd;
@@ -32,6 +33,7 @@
import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd;
import org.apache.cloudstack.api.command.user.vm.ListNicsCmd;
+import org.apache.cloudstack.api.response.AcquirePodIpCmdResponse;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@@ -72,6 +74,7 @@
import com.cloud.user.User;
import com.cloud.utils.Pair;
import com.cloud.utils.component.ManagerBase;
+import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.Nic;
import com.cloud.vm.NicProfile;
import com.cloud.vm.NicSecondaryIp;
@@ -571,6 +574,11 @@ public void expungeNics(VirtualMachineProfile vm) {
return null;
}
+ @Override
+ public Map<String, String> getSystemVMAccessDetails(VirtualMachine vm) {
+ return null;
+ }
+
/* (non-Javadoc)
* @see com.cloud.network.NetworkManager#implementNetwork(long, com.cloud.deploy.DeployDestination, com.cloud.vm.ReservationContext)
*/
@@ -603,9 +611,9 @@ public boolean destroyNetwork(long networkId, ReservationContext context, boolea
* @see com.cloud.network.NetworkManager#createGuestNetwork(long, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, com.cloud.user.Account, java.lang.Long, com.cloud.network.PhysicalNetwork, long, org.apache.cloudstack.acl.ControlledEntity.ACLType, java.lang.Boolean, java.lang.Long)
*/
@Override
- public Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, String networkDomain,
- Account owner, Long domainId, PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String gatewayv6,
- String cidrv6, Boolean displayNetworkEnabled, String isolatedPvlan ) throws ConcurrentOperationException, InsufficientCapacityException,
+ public Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, boolean bypassVlanOverlapCheck, String networkDomain,
+ Account owner, Long domainId, PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String gatewayv6,
+ String cidrv6, Boolean displayNetworkEnabled, String isolatedPvlan) throws ConcurrentOperationException, InsufficientCapacityException,
ResourceAllocationException {
// TODO Auto-generated method stub
return null;
@@ -911,4 +919,13 @@ public boolean configureNicSecondaryIp(NicSecondaryIp secIp, boolean isZoneSgEna
return null;
}
+ @Override
+ public boolean releasePodIp(ReleasePodIpCmdByAdmin ip) throws CloudRuntimeException {
+ return true;
+ }
+
+ @Override
+ public AcquirePodIpCmdResponse allocatePodIp(Account account, String zoneId, String podId) throws ResourceAllocationException, ConcurrentOperationException {
+ return null;
+ }
}
diff --git a/server/test/com/cloud/vpc/MockNetworkModelImpl.java b/server/test/com/cloud/vpc/MockNetworkModelImpl.java
index 89a7ab7068b..50d9b0f6425 100644
--- a/server/test/com/cloud/vpc/MockNetworkModelImpl.java
+++ b/server/test/com/cloud/vpc/MockNetworkModelImpl.java
@@ -33,6 +33,7 @@
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.GuestType;
+import com.cloud.network.Network.IpAddresses;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.NetworkModel;
@@ -845,7 +846,7 @@ public void checkIp6Parameters(String startIPv6, String endIPv6, String ip6Gatew
}
@Override
- public void checkRequestedIpAddresses(long networkId, String ip4, String ip6) throws InvalidParameterValueException {
+ public void checkRequestedIpAddresses(long networkId, IpAddresses ips) throws InvalidParameterValueException {
// TODO Auto-generated method stub
}
@@ -916,4 +917,9 @@ public boolean getNetworkEgressDefaultPolicy(Long networkId) {
return null;
}
+ @Override
+ public String getValidNetworkCidr(Network guestNetwork) {
+ return null;
+ }
+
}
diff --git a/server/test/com/cloud/vpc/dao/MockNetworkDaoImpl.java b/server/test/com/cloud/vpc/dao/MockNetworkDaoImpl.java
index 757b0245705..11f3f81f357 100644
--- a/server/test/com/cloud/vpc/dao/MockNetworkDaoImpl.java
+++ b/server/test/com/cloud/vpc/dao/MockNetworkDaoImpl.java
@@ -34,12 +34,8 @@
@DB()
public class MockNetworkDaoImpl extends GenericDaoBase<NetworkVO, Long> implements NetworkDao {
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#listByOwner(long)
- */
@Override
public List<NetworkVO> listByOwner(final long ownerId) {
- // TODO Auto-generated method stub
return null;
}
@@ -48,279 +44,146 @@
return null;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#listBy(long, long, long)
- */
@Override
public List<NetworkVO> listBy(final long accountId, final long offeringId, final long dataCenterId) {
- // TODO Auto-generated method stub
return null;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#listBy(long, long, java.lang.String, boolean)
- */
@Override
public List<NetworkVO> listBy(final long accountId, final long dataCenterId, final String cidr, final boolean skipVpc) {
- // TODO Auto-generated method stub
return null;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#listByZoneAndGuestType(long, long, com.cloud.network.Network.GuestType, java.lang.Boolean)
- */
@Override
public List<NetworkVO> listByZoneAndGuestType(final long accountId, final long dataCenterId, final GuestType type, final Boolean isSystem) {
- // TODO Auto-generated method stub
return null;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#persist(com.cloud.network.NetworkVO, boolean, java.util.Map)
- */
@Override
public NetworkVO persist(final NetworkVO network, final boolean gc, final Map<String, String> serviceProviderMap) {
- // TODO Auto-generated method stub
return null;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#createSearchBuilderForAccount()
- */
@Override
public SearchBuilder<NetworkAccountVO> createSearchBuilderForAccount() {
- // TODO Auto-generated method stub
return null;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#getNetworksForOffering(long, long, long)
- */
@Override
public List<NetworkVO> getNetworksForOffering(final long offeringId, final long dataCenterId, final long accountId) {
- // TODO Auto-generated method stub
return null;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#getNextAvailableMacAddress(long)
- */
@Override
public String getNextAvailableMacAddress(final long networkConfigId, Integer zoneMacIdentifier) {
- // TODO Auto-generated method stub
return null;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#listBy(long, long)
- */
@Override
public List<NetworkVO> listBy(final long accountId, final long networkId) {
- // TODO Auto-generated method stub
return null;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#countByZoneAndUri(long, java.lang.String)
- */
@Override
- public long countByZoneAndUri(final long zoneId, final String broadcastUri) {
- // TODO Auto-generated method stub
- return 0;
- }
-
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#countByZoneUriAndGuestType(long, java.lang.String, com.cloud.network.Network.GuestType)
- */
- @Override
- public long countByZoneUriAndGuestType(final long zoneId, final String broadcastUri, final GuestType guestType) {
- // TODO Auto-generated method stub
- return 0;
+ public List<NetworkVO> listByZoneAndUriAndGuestType(long zoneId, String broadcastUri, GuestType guestType) {
+ return null;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#listByZone(long)
- */
@Override
public List<NetworkVO> listByZone(final long zoneId) {
- // TODO Auto-generated method stub
return null;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#changeActiveNicsBy(long, int)
- */
@Override
public void changeActiveNicsBy(final long networkId, final int nicsCount) {
- // TODO Auto-generated method stub
-
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#getActiveNicsIn(long)
- */
@Override
public int getActiveNicsIn(final long networkId) {
- // TODO Auto-generated method stub
return 0;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#findNetworksToGarbageCollect()
- */
@Override
public List<Long> findNetworksToGarbageCollect() {
- // TODO Auto-generated method stub
return null;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#clearCheckForGc(long)
- */
@Override
public void clearCheckForGc(final long networkId) {
- // TODO Auto-generated method stub
-
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#listByZoneSecurityGroup(java.lang.Long)
- */
@Override
public List<NetworkVO> listByZoneSecurityGroup(final Long zoneId) {
- // TODO Auto-generated method stub
return null;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#addDomainToNetwork(long, long, java.lang.Boolean)
- */
@Override
public void addDomainToNetwork(final long networkId, final long domainId, final Boolean subdomainAccess) {
- // TODO Auto-generated method stub
-
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#listByPhysicalNetwork(long)
- */
@Override
public List<NetworkVO> listByPhysicalNetwork(final long physicalNetworkId) {
- // TODO Auto-generated method stub
return null;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#listSecurityGroupEnabledNetworks()
- */
@Override
public List<NetworkVO> listSecurityGroupEnabledNetworks() {
- // TODO Auto-generated method stub
return null;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#listByPhysicalNetworkTrafficType(long, com.cloud.network.Networks.TrafficType)
- */
@Override
public List<NetworkVO> listByPhysicalNetworkTrafficType(final long physicalNetworkId, final TrafficType trafficType) {
- // TODO Auto-generated method stub
return null;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#listBy(long, long, com.cloud.network.Network.GuestType, com.cloud.network.Networks.TrafficType)
- */
@Override
public List<NetworkVO> listBy(final long accountId, final long dataCenterId, final GuestType type, final TrafficType trafficType) {
- // TODO Auto-generated method stub
return null;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#listByPhysicalNetworkAndProvider(long, java.lang.String)
- */
@Override
public List<NetworkVO> listByPhysicalNetworkAndProvider(final long physicalNetworkId, final String providerName) {
- // TODO Auto-generated method stub
return null;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#persistNetworkServiceProviders(long, java.util.Map)
- */
@Override
public void persistNetworkServiceProviders(final long networkId, final Map<String, String> serviceProviderMap) {
- // TODO Auto-generated method stub
-
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#update(java.lang.Long, com.cloud.network.NetworkVO, java.util.Map)
- */
@Override
public boolean update(final Long networkId, final NetworkVO network, final Map<String, String> serviceProviderMap) {
- // TODO Auto-generated method stub
return false;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#listByZoneAndTrafficType(long, com.cloud.network.Networks.TrafficType)
- */
@Override
public List<NetworkVO> listByZoneAndTrafficType(final long zoneId, final TrafficType trafficType) {
- // TODO Auto-generated method stub
return null;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#setCheckForGc(long)
- */
@Override
public void setCheckForGc(final long networkId) {
- // TODO Auto-generated method stub
-
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#getNetworkCountByNetworkOffId(long)
- */
@Override
public int getNetworkCountByNetworkOffId(final long networkOfferingId) {
- // TODO Auto-generated method stub
return 0;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#countNetworksUserCanCreate(long)
- */
@Override
public long countNetworksUserCanCreate(final long ownerId) {
- // TODO Auto-generated method stub
return 0;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#listSourceNATEnabledNetworks(long, long, com.cloud.network.Network.GuestType)
- */
@Override
public List<NetworkVO> listSourceNATEnabledNetworks(final long accountId, final long dataCenterId, final GuestType type) {
- // TODO Auto-generated method stub
return null;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#getNetworkCountByVpcId(long)
- */
@Override
public int getNetworkCountByVpcId(final long vpcId) {
- // TODO Auto-generated method stub
return 0;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#listByVpc(long)
- */
@Override
public List<NetworkVO> listByVpc(final long vpcId) {
final List<NetworkVO> networks = new ArrayList<NetworkVO>();
@@ -328,21 +191,13 @@ public int getNetworkCountByVpcId(final long vpcId) {
return networks;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#getPrivateNetwork(java.lang.String, java.lang.String, long, long)
- */
@Override
public NetworkVO getPrivateNetwork(final String broadcastUri, final String cidr, final long accountId, final long zoneId, final Long netofferid) {
- // TODO Auto-generated method stub
return null;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#countVpcNetworks(long)
- */
@Override
public long countVpcNetworks(final long vpcId) {
- // TODO Auto-generated method stub
return 0;
}
@@ -351,24 +206,18 @@ public boolean updateState(final Network.State currentState, final Network.Event
return true;
}
- /* (non-Javadoc)
- * @see com.cloud.network.dao.NetworkDao#listNetworksByAccount(long, long, com.cloud.network.Network.GuestType, boolean)
- */
@Override
public List<NetworkVO> listNetworksByAccount(final long accountId, final long zoneId, final GuestType type, final boolean isSystem) {
- // TODO Auto-generated method stub
return null;
}
@Override
public List<NetworkVO> listRedundantNetworks() {
- // TODO Auto-generated method stub
return null;
}
@Override
public List<NetworkVO> listVpcNetworks() {
- // TODO Auto-generated method stub
return null;
}
@@ -381,4 +230,9 @@ public boolean updateState(final Network.State currentState, final Network.Event
public int getNonSystemNetworkCountByVpcId(final long vpcId) {
return 0;
}
-}
+
+ @Override
+ public List<NetworkVO> listNetworkVO(List<Long> idset) {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/server/test/org/apache/cloudstack/ca/CABackgroundTaskTest.java b/server/test/org/apache/cloudstack/ca/CABackgroundTaskTest.java
new file mode 100644
index 00000000000..564bbe36f6d
--- /dev/null
+++ b/server/test/org/apache/cloudstack/ca/CABackgroundTaskTest.java
@@ -0,0 +1,151 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.ca;
+
+import static org.apache.cloudstack.ca.CAManager.AutomaticCertRenewal;
+
+import java.lang.reflect.Field;
+import java.security.KeyPair;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.utils.identity.ManagementServerNode;
+import org.apache.cloudstack.utils.security.CertUtils;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+import com.cloud.host.Status;
+import com.cloud.host.dao.HostDao;
+import com.cloud.storage.Storage;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CABackgroundTaskTest {
+
+ @Mock
+ private CAManager caManager;
+ @Mock
+ private HostDao hostDao;
+
+ private String hostIp = "1.2.3.4";
+ private HostVO host = new HostVO(1L, "some.host",Host.Type.Routing, hostIp, "255.255.255.0", null, null, null, null, null, null, null, null, null, null,
+ UUID.randomUUID().toString(), Status.Up, "1.0", null, null, 1L, null, 0, 0, "aa", 0, Storage.StoragePoolType.NetworkFilesystem);
+
+ private X509Certificate expiredCertificate;
+ private Map<String, X509Certificate> certMap = new HashMap<>();
+ private CAManagerImpl.CABackgroundTask task;
+
+ @Before
+ public void setUp() throws Exception {
+ host.setManagementServerId(ManagementServerNode.getManagementServerId());
+ task = new CAManagerImpl.CABackgroundTask(caManager, hostDao);
+ final KeyPair keypair = CertUtils.generateRandomKeyPair(1024);
+ expiredCertificate = CertUtils.generateV3Certificate(null, keypair, keypair.getPublic(), "CN=ca", "SHA256withRSA", 0, null, null);
+
+ Mockito.when(hostDao.findByIp(Mockito.anyString())).thenReturn(host);
+ Mockito.when(caManager.getActiveCertificatesMap()).thenReturn(certMap);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ certMap.clear();
+ Mockito.reset(caManager);
+ Mockito.reset(hostDao);
+ }
+
+ private void overrideDefaultConfigValue(final ConfigKey configKey, final String name, final Object o) throws IllegalAccessException, NoSuchFieldException {
+ Field f = ConfigKey.class.getDeclaredField(name);
+ f.setAccessible(true);
+ f.set(configKey, o);
+ }
+
+ @Test
+ public void testNullCert() throws Exception {
+ certMap.put(hostIp, null);
+ Assert.assertTrue(certMap.size() == 1);
+ task.runInContext();
+ Assert.assertTrue(certMap.size() == 0);
+ }
+
+ @Test
+ public void testNullHost() throws Exception {
+ Mockito.when(hostDao.findByIp(Mockito.anyString())).thenReturn(null);
+ certMap.put(hostIp, expiredCertificate);
+ Assert.assertTrue(certMap.size() == 1);
+ task.runInContext();
+ Assert.assertTrue(certMap.size() == 0);
+ }
+
+ @Test
+ public void testAutoRenewalEnabledWithNoExceptionsOnProvisioning() throws Exception {
+ overrideDefaultConfigValue(AutomaticCertRenewal, "_defaultValue", "true");
+ host.setManagementServerId(ManagementServerNode.getManagementServerId());
+ certMap.put(hostIp, expiredCertificate);
+ Assert.assertTrue(certMap.size() == 1);
+ task.runInContext();
+ Mockito.verify(caManager, Mockito.times(1)).provisionCertificate(host, false, null);
+ Mockito.verify(caManager, Mockito.times(0)).sendAlert(Mockito.any(Host.class), Mockito.anyString(), Mockito.anyString());
+ }
+
+ @Test
+ public void testAutoRenewalEnabledWithExceptionsOnProvisioning() throws Exception {
+ overrideDefaultConfigValue(AutomaticCertRenewal, "_defaultValue", "true");
+ Mockito.when(caManager.provisionCertificate(Mockito.any(Host.class), Mockito.anyBoolean(), Mockito.anyString())).thenThrow(new CloudRuntimeException("some error"));
+ host.setManagementServerId(ManagementServerNode.getManagementServerId());
+ certMap.put(hostIp, expiredCertificate);
+ Assert.assertTrue(certMap.size() == 1);
+ task.runInContext();
+ Mockito.verify(caManager, Mockito.times(1)).provisionCertificate(host, false, null);
+ Mockito.verify(caManager, Mockito.times(1)).sendAlert(Mockito.any(Host.class), Mockito.anyString(), Mockito.anyString());
+ }
+
+ @Test
+ public void testAutoRenewalDisabled() throws Exception {
+ overrideDefaultConfigValue(AutomaticCertRenewal, "_defaultValue", "false");
+ certMap.put(hostIp, expiredCertificate);
+ Assert.assertTrue(certMap.size() == 1);
+ // First round
+ task.runInContext();
+ Mockito.verify(caManager, Mockito.times(0)).provisionCertificate(Mockito.any(Host.class), Mockito.anyBoolean(), Mockito.anyString());
+ Mockito.verify(caManager, Mockito.times(1)).sendAlert(Mockito.any(Host.class), Mockito.anyString(), Mockito.anyString());
+ Mockito.reset(caManager);
+ // Second round
+ task.runInContext();
+ Mockito.verify(caManager, Mockito.times(0)).provisionCertificate(Mockito.any(Host.class), Mockito.anyBoolean(), Mockito.anyString());
+ Mockito.verify(caManager, Mockito.times(0)).sendAlert(Mockito.any(Host.class), Mockito.anyString(), Mockito.anyString());
+ }
+
+ @Test
+ public void testGetDelay() throws Exception {
+ Assert.assertTrue(task.getDelay() == CAManager.CABackgroundJobDelay.value() * 1000L);
+ }
+
+}
\ No newline at end of file
diff --git a/server/test/org/apache/cloudstack/ca/CAManagerImplTest.java b/server/test/org/apache/cloudstack/ca/CAManagerImplTest.java
new file mode 100644
index 00000000000..14ecc971d5f
--- /dev/null
+++ b/server/test/org/apache/cloudstack/ca/CAManagerImplTest.java
@@ -0,0 +1,121 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.ca;
+
+import java.lang.reflect.Field;
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.cert.X509Certificate;
+import java.util.Collections;
+
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.framework.ca.CAProvider;
+import org.apache.cloudstack.framework.ca.Certificate;
+import org.apache.cloudstack.utils.security.CertUtils;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.Answer;
+import com.cloud.certificate.CrlVO;
+import com.cloud.certificate.dao.CrlDao;
+import com.cloud.host.Host;
+import com.cloud.host.dao.HostDao;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CAManagerImplTest {
+
+ @Mock
+ private HostDao hostDao;
+ @Mock
+ private CrlDao crlDao;
+ @Mock
+ private AgentManager agentManager;
+ @Mock
+ private CAProvider caProvider;
+
+ private CAManagerImpl caManager;
+
+ private void addField(final CAManagerImpl provider, final String name, final Object o) throws IllegalAccessException, NoSuchFieldException {
+ Field f = CAManagerImpl.class.getDeclaredField(name);
+ f.setAccessible(true);
+ f.set(provider, o);
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ caManager = new CAManagerImpl();
+ addField(caManager, "crlDao", crlDao);
+ addField(caManager, "hostDao", hostDao);
+ addField(caManager, "agentManager", agentManager);
+ addField(caManager, "configuredCaProvider", caProvider);
+
+ Mockito.when(caProvider.getProviderName()).thenReturn("root");
+ caManager.setCaProviders(Collections.singletonList(caProvider));
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ Mockito.reset(crlDao);
+ Mockito.reset(agentManager);
+ Mockito.reset(caProvider);
+ }
+
+ @Test(expected = ServerApiException.class)
+ public void testIssueCertificateThrowsException() throws Exception {
+ caManager.issueCertificate(null, null, null, 1, null);
+ }
+
+ @Test
+ public void testIssueCertificate() throws Exception {
+ caManager.issueCertificate(null, Collections.singletonList("domain.example"), null, 1, null);
+ Mockito.verify(caProvider, Mockito.times(1)).issueCertificate(Mockito.anyList(), Mockito.anyList(), Mockito.anyInt());
+ Mockito.verify(caProvider, Mockito.times(0)).issueCertificate(Mockito.anyString(), Mockito.anyList(), Mockito.anyList(), Mockito.anyInt());
+ }
+
+ @Test
+ public void testRevokeCertificate() throws Exception {
+ final CrlVO crl = new CrlVO(CertUtils.generateRandomBigInt(), "some.domain", "some-uuid");
+ Mockito.when(crlDao.revokeCertificate(Mockito.any(BigInteger.class), Mockito.anyString())).thenReturn(crl);
+ Mockito.when(caProvider.revokeCertificate(Mockito.any(BigInteger.class), Mockito.anyString())).thenReturn(true);
+ Assert.assertTrue(caManager.revokeCertificate(crl.getCertSerial(), crl.getCertCn(), null));
+ Mockito.verify(caProvider, Mockito.times(1)).revokeCertificate(Mockito.any(BigInteger.class), Mockito.anyString());
+ }
+
+ @Test
+ public void testProvisionCertificate() throws Exception {
+ final Host host = Mockito.mock(Host.class);
+ Mockito.when(host.getPrivateIpAddress()).thenReturn("1.2.3.4");
+ final KeyPair keyPair = CertUtils.generateRandomKeyPair(1024);
+ final X509Certificate certificate = CertUtils.generateV3Certificate(null, keyPair, keyPair.getPublic(), "CN=ca", "SHA256withRSA", 365, null, null);
+ Mockito.when(caProvider.issueCertificate(Mockito.anyString(), Mockito.anyList(), Mockito.anyList(), Mockito.anyInt())).thenReturn(new Certificate(certificate, null, Collections.singletonList(certificate)));
+ Mockito.when(agentManager.send(Mockito.anyLong(), Mockito.any(SetupKeyStoreCommand.class))).thenReturn(new SetupKeystoreAnswer("someCsr"));
+ Mockito.when(agentManager.reconnect(Mockito.anyLong())).thenReturn(true);
+ Assert.assertTrue(caManager.provisionCertificate(host, true, null));
+ Mockito.verify(agentManager, Mockito.times(2)).send(Mockito.anyLong(), Mockito.any(Answer.class));
+ Mockito.verify(agentManager, Mockito.times(1)).reconnect(Mockito.anyLong());
+ }
+}
\ No newline at end of file
diff --git a/server/test/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementServiceTest.java b/server/test/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementServiceTest.java
index 69f03ff674b..7f848191524 100644
--- a/server/test/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementServiceTest.java
+++ b/server/test/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementServiceTest.java
@@ -101,7 +101,7 @@ public void testGetOutOfBandManagementOptionsValid() {
OutOfBandManagement config = new OutOfBandManagementVO(123L);
config.setAddress("localhost");
config.setDriver("ipmitool");
- config.setPort(1234);
+ config.setPort("1234");
ImmutableMap<OutOfBandManagement.Option, String> options = oobmService.getOptions(config);
Assert.assertEquals(options.get(OutOfBandManagement.Option.ADDRESS), "localhost");
Assert.assertEquals(options.get(OutOfBandManagement.Option.DRIVER), "ipmitool");
diff --git a/server/test/org/apache/cloudstack/poll/BackgroundPollManagerImplTest.java b/server/test/org/apache/cloudstack/poll/BackgroundPollManagerImplTest.java
new file mode 100644
index 00000000000..f35d49cefed
--- /dev/null
+++ b/server/test/org/apache/cloudstack/poll/BackgroundPollManagerImplTest.java
@@ -0,0 +1,85 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.poll;
+
+import org.apache.cloudstack.managed.context.ManagedContextRunnable;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class BackgroundPollManagerImplTest {
+
+ private BackgroundPollManagerImpl pollManager;
+ private DummyPollTask pollTask;
+
+ private class DummyPollTask extends ManagedContextRunnable implements BackgroundPollTask {
+ private boolean didIRun = false;
+ private long counter = 0;
+
+ public boolean didItRan() {
+ return didIRun;
+ }
+
+ public long getCounter() {
+ return counter;
+ }
+
+ @Override
+ protected void runInContext() {
+ didIRun = true;
+ counter++;
+ }
+
+ @Override
+ public Long getDelay() {
+ return null;
+ }
+
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ pollManager = new BackgroundPollManagerImpl();
+ pollTask = new DummyPollTask();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ pollManager.stop();
+ }
+
+ @Test
+ public void testSubmitValidTask() throws Exception {
+ Assert.assertFalse(pollTask.didItRan());
+ Assert.assertTrue(pollTask.getCounter() == 0);
+
+ pollManager.submitTask(pollTask);
+ pollManager.start();
+ Thread.sleep(pollManager.getInitialDelay()*2);
+
+ Assert.assertTrue(pollTask.didItRan());
+ Assert.assertTrue(pollTask.getCounter() > 0);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testSubmitNullTask() throws Exception {
+ pollManager.submitTask(null);
+ }
+
+}
\ No newline at end of file
diff --git a/server/test/org/cloud/network/router/deployment/VpcRouterDeploymentDefinitionTest.java b/server/test/org/cloud/network/router/deployment/VpcRouterDeploymentDefinitionTest.java
index 13c20ae7e50..e4ef9f5fc27 100644
--- a/server/test/org/cloud/network/router/deployment/VpcRouterDeploymentDefinitionTest.java
+++ b/server/test/org/cloud/network/router/deployment/VpcRouterDeploymentDefinitionTest.java
@@ -168,9 +168,30 @@ public void testGetNumberOfRoutersToDeploy() {
assertEquals("If there is already a router found, there is no need to deploy more", 0, deployment.getNumberOfRoutersToDeploy());
}
+ protected void driveTestPrepareDeployment(final boolean isRedundant, final boolean isPublicNw) {
+ // Prepare
+ when(vpcMgr.isSrcNatIpRequired(mockVpc.getVpcOfferingId())).thenReturn(isPublicNw);
+
+ // Execute
+ final boolean canProceedDeployment = deployment.prepareDeployment();
+ // Assert
+ assertTrue("There are no preconditions for Vpc Deployment, thus it should always pass", canProceedDeployment);
+ assertEquals(isPublicNw, deployment.isPublicNetwork());
+ }
+
+ @Test
+ public void testPrepareDeploymentPublicNw() {
+ driveTestPrepareDeployment(true, true);
+ }
+
+ @Test
+ public void testPrepareDeploymentNonRedundant() {
+ driveTestPrepareDeployment(false, true);
+ }
+
@Test
- public void testPrepareDeployment() {
- assertTrue("There are no preconditions for Vpc Deployment, thus it should always pass", deployment.prepareDeployment());
+ public void testPrepareDeploymentRedundantNonPublicNw() {
+ driveTestPrepareDeployment(true, false);
}
@Test
@@ -246,6 +267,7 @@ public void testFindSourceNatIP() throws InsufficientAddressCapacityException, C
// Prepare
final PublicIp publicIp = mock(PublicIp.class);
when(vpcMgr.assignSourceNatIpAddressToVpc(mockOwner, mockVpc)).thenReturn(publicIp);
+ deployment.isPublicNetwork = true;
// Execute
deployment.findSourceNatIP();
diff --git a/server/test/resources/db.properties b/server/test/resources/db.properties
index e9355a3db35..5eefc45ea50 100644
--- a/server/test/resources/db.properties
+++ b/server/test/resources/db.properties
@@ -17,7 +17,7 @@
# management server clustering parameters, change cluster.node.IP to the machine IP address
-# in which the management server(Tomcat) is running
+# in which the management server is running
cluster.node.IP=127.0.0.1
cluster.servlet.port=9090
diff --git a/services/console-proxy-rdp/rdpconsole/pom.xml b/services/console-proxy-rdp/rdpconsole/pom.xml
index 9dbe106479d..f16d2315046 100755
--- a/services/console-proxy-rdp/rdpconsole/pom.xml
+++ b/services/console-proxy-rdp/rdpconsole/pom.xml
@@ -27,7 +27,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-services</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/services/console-proxy/plugin/pom.xml b/services/console-proxy/plugin/pom.xml
index 40d464e3683..db7774f61f5 100644
--- a/services/console-proxy/plugin/pom.xml
+++ b/services/console-proxy/plugin/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-service-console-proxy</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
</project>
diff --git a/services/console-proxy/pom.xml b/services/console-proxy/pom.xml
index d88f0e2d119..e219b13b9cc 100644
--- a/services/console-proxy/pom.xml
+++ b/services/console-proxy/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-services</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<build>
diff --git a/services/console-proxy/server/pom.xml b/services/console-proxy/server/pom.xml
index d61049cf15f..7ec58bbd2c5 100644
--- a/services/console-proxy/server/pom.xml
+++ b/services/console-proxy/server/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-service-console-proxy</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxySecureServerFactoryImpl.java b/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxySecureServerFactoryImpl.java
index 5df971c46d0..df879fe9e82 100644
--- a/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxySecureServerFactoryImpl.java
+++ b/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxySecureServerFactoryImpl.java
@@ -91,6 +91,8 @@ public void configure(HttpsParameters params) {
SSLParameters sslparams = c.getDefaultSSLParameters();
params.setSSLParameters(sslparams);
+ params.setProtocols(SSLUtils.getRecommendedProtocols());
+ params.setCipherSuites(SSLUtils.getRecommendedCiphers());
// statement above could throw IAE if any params invalid.
// eg. if app has a UI and parameters supplied by a user.
}
@@ -110,7 +112,8 @@ public SSLServerSocket createSSLServerSocket(int port) throws IOException {
SSLServerSocket srvSock = null;
SSLServerSocketFactory ssf = sslContext.getServerSocketFactory();
srvSock = (SSLServerSocket)ssf.createServerSocket(port);
- srvSock.setEnabledProtocols(SSLUtils.getSupportedProtocols(srvSock.getEnabledProtocols()));
+ srvSock.setEnabledProtocols(SSLUtils.getRecommendedProtocols());
+ srvSock.setEnabledCipherSuites(SSLUtils.getRecommendedCiphers());
s_logger.info("create SSL server socket on port: " + port);
return srvSock;
diff --git a/services/iam/plugin/pom.xml b/services/iam/plugin/pom.xml
index 22ca14c5275..e7e2aa4e1a9 100644
--- a/services/iam/plugin/pom.xml
+++ b/services/iam/plugin/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-service-iam</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/services/iam/plugin/test/resources/db.properties b/services/iam/plugin/test/resources/db.properties
index a672d63f799..fc2fb33669c 100644
--- a/services/iam/plugin/test/resources/db.properties
+++ b/services/iam/plugin/test/resources/db.properties
@@ -17,7 +17,7 @@
# management server clustering parameters, change cluster.node.IP to the machine IP address
-# in which the management server(Tomcat) is running
+# in which the management server is running
cluster.node.IP=127.0.0.1
cluster.servlet.port=9090
region.id=1
diff --git a/services/iam/server/pom.xml b/services/iam/server/pom.xml
index 9546292fa16..fb9c4ed160d 100644
--- a/services/iam/server/pom.xml
+++ b/services/iam/server/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-service-iam</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/services/pom.xml b/services/pom.xml
index 381cd424b7d..3972f951d45 100644
--- a/services/pom.xml
+++ b/services/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<build>
diff --git a/services/secondary-storage/controller/pom.xml b/services/secondary-storage/controller/pom.xml
index 1ab8f9edc1f..d90c985a46d 100644
--- a/services/secondary-storage/controller/pom.xml
+++ b/services/secondary-storage/controller/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-service-secondary-storage</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/services/secondary-storage/controller/src/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java b/services/secondary-storage/controller/src/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java
index 79c6bab1b4b..273fdd0d116 100644
--- a/services/secondary-storage/controller/src/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java
+++ b/services/secondary-storage/controller/src/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java
@@ -123,6 +123,7 @@
import com.cloud.utils.DateUtil;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
+import com.cloud.utils.StringUtils;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.GlobalLock;
import com.cloud.utils.db.QueryBuilder;
@@ -1118,7 +1119,7 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl
StringBuilder buf = profile.getBootArgsBuilder();
buf.append(" template=domP type=secstorage");
- buf.append(" host=").append(ApiServiceConfiguration.ManagementHostIPAdr.value());
+ buf.append(" host=").append(StringUtils.shuffleCSVList(ApiServiceConfiguration.ManagementHostIPAdr.value()));
buf.append(" port=").append(_mgmtPort);
buf.append(" name=").append(profile.getVirtualMachine().getHostName());
diff --git a/services/secondary-storage/pom.xml b/services/secondary-storage/pom.xml
index eb54f09ee48..d91665155ca 100644
--- a/services/secondary-storage/pom.xml
+++ b/services/secondary-storage/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-services</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modules>
diff --git a/services/secondary-storage/server/pom.xml b/services/secondary-storage/server/pom.xml
index 064371e2dfc..b1b9e45f2e5 100644
--- a/services/secondary-storage/server/pom.xml
+++ b/services/secondary-storage/server/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-service-secondary-storage</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java b/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
index 60424c1af3b..eb6f220f7ca 100644
--- a/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
+++ b/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
@@ -16,6 +16,26 @@
// under the License.
package org.apache.cloudstack.storage.resource;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.InetAddress;
+import java.net.URI;
+import java.net.UnknownHostException;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import javax.naming.ConfigurationException;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.CheckHealthAnswer;
@@ -54,6 +74,7 @@
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.host.Host;
import com.cloud.host.Host.Type;
+import com.cloud.configuration.Resource;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.resource.ServerResourceBase;
import com.cloud.storage.DataStoreRole;
@@ -116,6 +137,7 @@
import org.apache.cloudstack.storage.to.TemplateObjectTO;
import org.apache.cloudstack.storage.to.VolumeObjectTO;
import org.apache.cloudstack.utils.imagestore.ImageStoreUtil;
+import org.apache.cloudstack.utils.security.DigestHelper;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
@@ -131,29 +153,6 @@
import org.joda.time.DateTime;
import org.joda.time.format.ISODateTimeFormat;
-import javax.naming.ConfigurationException;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.math.BigInteger;
-import java.net.InetAddress;
-import java.net.URI;
-import java.net.UnknownHostException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
import static com.cloud.utils.StringUtils.join;
import static com.cloud.utils.storage.S3.S3Utils.putFile;
import static java.lang.String.format;
@@ -460,7 +459,7 @@ protected Answer copySnapshotToTemplateFromNfsToNfsXenserver(CopyCommand cmd, Sn
FormatInfo info = processor.process(destPath, null, templateUuid);
TemplateLocation loc = new TemplateLocation(_storage, destPath);
- loc.create(1, true, templateUuid);
+ loc.create(destData.getId(), true, templateUuid);
loc.addFormat(info);
loc.save();
TemplateProp prop = loc.getTemplateInfo();
@@ -525,6 +524,8 @@ protected Answer copySnapshotToTemplateFromNfsToNfs(CopyCommand cmd, SnapshotObj
bufferWriter.write("\n");
long size = _storage.getSize(destFileFullPath);
bufferWriter.write("size=" + size);
+ bufferWriter.close();
+ writer.close();
/**
* Snapshots might be in either QCOW2 or RAW image format
@@ -548,7 +549,7 @@ protected Answer copySnapshotToTemplateFromNfsToNfs(CopyCommand cmd, SnapshotObj
FormatInfo info = processor.process(destPath, null, templateName);
TemplateLocation loc = new TemplateLocation(_storage, destPath);
- loc.create(1, true, destData.getName());
+ loc.create(destData.getId(), true, destData.getName());
loc.addFormat(info);
loc.save();
@@ -1311,46 +1312,24 @@ private Answer execute(ComputeChecksumCommand cmd) {
parent += File.separator;
}
String absoluteTemplatePath = parent + relativeTemplatePath;
- MessageDigest digest;
- String checksum = null;
+ String algorithm = cmd.getAlgorithm();
File f = new File(absoluteTemplatePath);
- InputStream is = null;
- byte[] buffer = new byte[8192];
- int read = 0;
if (s_logger.isDebugEnabled()) {
s_logger.debug("parent path " + parent + " relative template path " + relativeTemplatePath);
}
+ String checksum = null;
- try {
- digest = MessageDigest.getInstance("MD5");
- is = new FileInputStream(f);
- while ((read = is.read(buffer)) > 0) {
- digest.update(buffer, 0, read);
- }
- byte[] md5sum = digest.digest();
- BigInteger bigInt = new BigInteger(1, md5sum);
- checksum = bigInt.toString(16);
+ try (InputStream is = new FileInputStream(f);){
+ checksum = DigestHelper.digest(algorithm, is).toString();
if (s_logger.isDebugEnabled()) {
s_logger.debug("Successfully calculated checksum for file " + absoluteTemplatePath + " - " + checksum);
}
-
} catch (IOException e) {
- String logMsg = "Unable to process file for MD5 - " + absoluteTemplatePath;
+ String logMsg = "Unable to process file for " + algorithm + " - " + absoluteTemplatePath;
s_logger.error(logMsg);
return new Answer(cmd, false, checksum);
} catch (NoSuchAlgorithmException e) {
return new Answer(cmd, false, checksum);
- } finally {
- try {
- if (is != null) {
- is.close();
- }
- } catch (IOException e) {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Could not close the file " + absoluteTemplatePath);
- }
- return new Answer(cmd, false, checksum);
- }
}
return new Answer(cmd, true, checksum);
@@ -2231,9 +2210,10 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
if (_inSystemVM) {
_localgw = (String)params.get("localgw");
if (_localgw != null) { // can only happen inside service vm
- String mgmtHost = (String)params.get("host");
- addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, mgmtHost);
-
+ String mgmtHosts = (String)params.get("host");
+ for (final String mgmtHost : mgmtHosts.split(",")) {
+ addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, mgmtHost);
+ }
String internalDns1 = (String)params.get("internaldns1");
if (internalDns1 == null) {
s_logger.warn("No DNS entry found during configuration of NfsSecondaryStorage");
@@ -2828,7 +2808,7 @@ private synchronized void checkSecondaryStorageResourceLimit(TemplateOrVolumePos
int accountDirSizeInGB = getSizeInGB(accountTemplateDirSize + accountSnapshotDirSize + accountVolumeDirSize);
int defaultMaxAccountSecondaryStorageInGB = Integer.parseInt(cmd.getDefaultMaxAccountSecondaryStorage());
- if ((accountDirSizeInGB + contentLengthInGB) > defaultMaxAccountSecondaryStorageInGB) {
+ if (defaultMaxAccountSecondaryStorageInGB != Resource.RESOURCE_UNLIMITED && (accountDirSizeInGB + contentLengthInGB) > defaultMaxAccountSecondaryStorageInGB) {
s_logger.error("accountDirSizeInGb: " + accountDirSizeInGB + " defaultMaxAccountSecondaryStorageInGB: " + defaultMaxAccountSecondaryStorageInGB + " contentLengthInGB:"
+ contentLengthInGB);
String errorMessage = "Maximum number of resources of type secondary_storage for account has exceeded";
@@ -3048,4 +3028,5 @@ private TemplateOrVolumePostUploadCommand getTemplateOrVolumePostUploadCmd(Strin
}
return cmd;
}
+
}
diff --git a/services/secondary-storage/server/src/org/apache/cloudstack/storage/template/DownloadManagerImpl.java b/services/secondary-storage/server/src/org/apache/cloudstack/storage/template/DownloadManagerImpl.java
index 40a1e1cdde0..833ef090f53 100644
--- a/services/secondary-storage/server/src/org/apache/cloudstack/storage/template/DownloadManagerImpl.java
+++ b/services/secondary-storage/server/src/org/apache/cloudstack/storage/template/DownloadManagerImpl.java
@@ -21,10 +21,8 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.math.BigInteger;
import java.net.URI;
import java.net.URISyntaxException;
-import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -84,6 +82,8 @@
import com.cloud.utils.script.OutputInterpreter;
import com.cloud.utils.script.Script;
import com.cloud.utils.storage.QCOW2Utils;
+import org.apache.cloudstack.utils.security.ChecksumValue;
+import org.apache.cloudstack.utils.security.DigestHelper;
public class DownloadManagerImpl extends ManagerBase implements DownloadManager {
private String _name;
@@ -315,33 +315,11 @@ public void setDownloadStatus(String jobId, Status status) {
}
}
- private String computeCheckSum(File f) {
- byte[] buffer = new byte[8192];
- int read = 0;
- MessageDigest digest;
- String checksum = null;
- InputStream is = null;
- try {
- digest = MessageDigest.getInstance("MD5");
- is = new FileInputStream(f);
- while ((read = is.read(buffer)) > 0) {
- digest.update(buffer, 0, read);
- }
- byte[] md5sum = digest.digest();
- BigInteger bigInt = new BigInteger(1, md5sum);
- checksum = String.format("%032x", bigInt);
- return checksum;
+ private ChecksumValue computeCheckSum(String algorithm, File f) throws NoSuchAlgorithmException {
+ try (InputStream is = new FileInputStream(f);) {
+ return DigestHelper.digest(algorithm, is);
} catch (IOException e) {
return null;
- } catch (NoSuchAlgorithmException e) {
- return null;
- } finally {
- try {
- if (is != null)
- is.close();
- } catch (IOException e) {
- return null;
- }
}
}
@@ -357,12 +335,8 @@ private String postRemoteDownload(String jobId) {
// The QCOW2 is the only format with a header,
// and as such can be easily read.
- try {
- InputStream inputStream = td.getS3ObjectInputStream();
-
+ try (InputStream inputStream = td.getS3ObjectInputStream();) {
dnld.setTemplatesize(QCOW2Utils.getVirtualSize(inputStream));
-
- inputStream.close();
}
catch (IOException e) {
result = "Couldn't read QCOW2 virtual size. Error: " + e.getMessage();
@@ -398,11 +372,22 @@ private String postLocalDownload(String jobId) {
ResourceType resourceType = dnld.getResourceType();
File originalTemplate = new File(td.getDownloadLocalPath());
- String checkSum = computeCheckSum(originalTemplate);
- if (checkSum == null) {
+ ChecksumValue oldValue = new ChecksumValue(dnld.getChecksum());
+ ChecksumValue newValue = null;
+ try {
+ newValue = computeCheckSum(oldValue.getAlgorithm(), originalTemplate);
+ } catch (NoSuchAlgorithmException e) {
+ return "checksum algorithm not recognised: " + oldValue.getAlgorithm();
+ }
+ if(StringUtils.isNotBlank(dnld.getChecksum()) && ! oldValue.equals(newValue)) {
+ return "checksum \"" + newValue +"\" didn't match the given value, \"" + oldValue + "\"";
+ }
+ String checksum = newValue.getChecksum();
+ if (checksum == null) {
s_logger.warn("Something wrong happened when try to calculate the checksum of downloaded template!");
}
- dnld.setCheckSum(checkSum);
+
+ dnld.setCheckSum(checksum);
int imgSizeGigs = (int)Math.ceil(_storage.getSize(td.getDownloadLocalPath()) * 1.0d / (1024 * 1024 * 1024));
imgSizeGigs++; // add one just in case
@@ -435,11 +420,7 @@ private String postLocalDownload(String jobId) {
scr.add("-n", templateFilename);
scr.add("-t", resourcePath);
- scr.add("-f", td.getDownloadLocalPath()); // this is the temporary
- // template file downloaded
- if (dnld.getChecksum() != null && dnld.getChecksum().length() > 1) {
- scr.add("-c", dnld.getChecksum());
- }
+ scr.add("-f", td.getDownloadLocalPath()); // this is the temporary template file downloaded
scr.add("-u"); // cleanup
String result;
result = scr.execute();
@@ -707,6 +688,10 @@ public DownloadAnswer handleDownloadCommand(SecondaryStorageResource resource, D
return new DownloadAnswer("Invalid Name", VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR);
}
+ if(! DigestHelper.isAlgorithmSupported(cmd.getChecksum())) {
+ return new DownloadAnswer("invalid algorithm: " + cmd.getChecksum(), VMTemplateStorageResourceAssoc.Status.NOT_DOWNLOADED);
+ }
+
DataStoreTO dstore = cmd.getDataStore();
String installPathPrefix = cmd.getInstallPath();
// for NFS, we need to get mounted path
@@ -865,17 +850,6 @@ private String getInstallPath(String jobId) {
result.put(tInfo.getTemplateName(), tInfo);
s_logger.debug("Added template name: " + tInfo.getTemplateName() + ", path: " + tmplt);
}
- /*
- for (String tmplt : isoTmplts) {
- String tmp[];
- tmp = tmplt.split("/");
- String tmpltName = tmp[tmp.length - 2];
- tmplt = tmplt.substring(tmplt.lastIndexOf("iso/"));
- TemplateInfo tInfo = new TemplateInfo(tmpltName, tmplt, false);
- s_logger.debug("Added iso template name: " + tmpltName + ", path: " + tmplt);
- result.put(tmpltName, tInfo);
- }
- */
return result;
}
diff --git a/setup/bindir/cloud-migrate-databases.in b/setup/bindir/cloud-migrate-databases.in
index 513e60b75df..95d04d45606 100644
--- a/setup/bindir/cloud-migrate-databases.in
+++ b/setup/bindir/cloud-migrate-databases.in
@@ -39,7 +39,7 @@ from cloud_utils import check_selinux, CheckFailed, resolves_to_ipv6
import cloud_utils
# RUN ME LIKE THIS
-# python setup/bindir/cloud-migrate-databases.in --config=client/tomcatconf/override/db.properties --resourcedir=setup/db --dry-run
+# python setup/bindir/cloud-migrate-databases.in --config=client/conf/override/db.properties --resourcedir=setup/db --dry-run
# --dry-run makes it so the changes to the database in the context of the migrator are rolled back
# This program / library breaks down as follows:
diff --git a/setup/bindir/cloud-set-guest-sshkey-configdrive.in b/setup/bindir/cloud-set-guest-sshkey-configdrive.in
index df10b436035..e8466e8f56a 100644
--- a/setup/bindir/cloud-set-guest-sshkey-configdrive.in
+++ b/setup/bindir/cloud-set-guest-sshkey-configdrive.in
@@ -84,7 +84,7 @@ else
exit 1
fi
-homedir=$(grep ^$user /etc/passwd|awk -F ":" '{print $6}')
+homedir=$(getent passwd $user|awk -F ":" '{print $6}')
sshdir=$homedir/.ssh
authorized=$sshdir/authorized_keys
diff --git a/setup/bindir/cloud-set-guest-sshkey.in b/setup/bindir/cloud-set-guest-sshkey.in
index 80e40646ad3..321c8dd2fec 100755
--- a/setup/bindir/cloud-set-guest-sshkey.in
+++ b/setup/bindir/cloud-set-guest-sshkey.in
@@ -49,7 +49,7 @@ if [ -z "$SSHKEY_SERVER_IP" ]; then
logger -t "cloud" "Unable to determine the password server, falling back to data-server"
SSHKEY_SERVER_IP=data-server
fi
-
+
logger -t "cloud" "Sending request to ssh key server at $SSHKEY_SERVER_IP"
publickey=$(wget -q -t 3 -T 20 -O - http://$SSHKEY_SERVER_IP/latest/public-keys)
if [ $? -eq 0 ]; then
@@ -67,7 +67,7 @@ if [ -z "$publickey" ]; then
exit 1
fi
-homedir=$(grep ^$user /etc/passwd|awk -F ":" '{print $6}')
+homedir=$(getent passwd $user|awk -F ":" '{print $6}')
sshdir=$homedir/.ssh
authorized=$sshdir/authorized_keys
diff --git a/setup/bindir/cloud-setup-databases.in b/setup/bindir/cloud-setup-databases.in
index 08a3cc937c3..0e66cfa68ae 100755
--- a/setup/bindir/cloud-setup-databases.in
+++ b/setup/bindir/cloud-setup-databases.in
@@ -388,7 +388,7 @@ for example:
def processEncryptionStuff(self):
def encrypt(input):
- cmd = ['java','-classpath','"' + self.encryptionJarPath + '"','org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI', 'encrypt.sh', 'input=%s'%input, 'password=%s'%self.mgmtsecretkey,'verbose=false']
+ cmd = ['java','-Djava.security.egd=file:/dev/urandom','-classpath','"' + self.encryptionJarPath + '"','org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI', 'encrypt.sh', 'input=%s'%input, 'password=%s'%self.mgmtsecretkey,'verbose=false']
return runCmd(cmd).strip('\r\n')
def saveMgmtServerSecretKey():
diff --git a/setup/bindir/cloud-setup-encryption.in b/setup/bindir/cloud-setup-encryption.in
index a617d498162..0c9b650fdb6 100755
--- a/setup/bindir/cloud-setup-encryption.in
+++ b/setup/bindir/cloud-setup-encryption.in
@@ -58,7 +58,6 @@ class DBDeployer(object):
isDebug = False
mgmtsecretkey = None
dbsecretkey = None
- keyStorePassphrase = "vmops.com"
encryptiontype = None
dbConfPath = r"@MSCONF@"
dbDotProperties = {}
@@ -198,9 +197,6 @@ for example:
def encryptDBSecretKey():
self.putDbProperty('db.cloud.encrypt.secret', formatEncryptResult(encrypt(self.dbsecretkey)))
- def encryptKeyStorePassphrase():
- self.putDbProperty('db.cloud.keyStorePassphrase', formatEncryptResult(encrypt(self.keyStorePassphrase)))
-
def encryptDBPassword():
dbPassword = self.getDbProperty('db.cloud.password')
if dbPassword == '': return # Don't encrypt empty password
@@ -216,7 +212,6 @@ for example:
self.putDbProperty("db.cloud.encryption.type", self.encryptiontype)
saveMgmtServerSecretKey()
encryptDBSecretKey()
- encryptKeyStorePassphrase()
encryptDBPassword()
self.info(None, True)
@@ -225,7 +220,6 @@ for example:
self.encryptiontype = self.options.encryptiontype
self.mgmtsecretkey = self.options.mgmtsecretkey
self.dbsecretkey = self.options.dbsecretkey
- self.keyStorePassphrase = self.options.keyStorePassphrase
self.isDebug = self.options.debug
@@ -248,9 +242,7 @@ for example:
help="Secret key used to encrypt confidential parameters in db.properties. A string, default is password")
self.parser.add_option("-k", "--database-secretkey", action="store", type="string", dest="dbsecretkey", default="password",
help="Secret key used to encrypt sensitive database values. A string, default is password")
- self.parser.add_option("-p", "--keystore-passphrase", action="store", type="string", dest="keyStorePassphrase", default="vmops.com",
- help="Passphrase used while generating jks file for ssl communication. A string, default is vmops.com")
-
+
(self.options, self.args) = self.parser.parse_args()
parseOtherOptions()
validateParameters()
diff --git a/setup/db/db/schema-41000to41100-cleanup.sql b/setup/db/db/schema-41000to41100-cleanup.sql
new file mode 100644
index 00000000000..1307173148a
--- /dev/null
+++ b/setup/db/db/schema-41000to41100-cleanup.sql
@@ -0,0 +1,24 @@
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements. See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership. The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing,
+-- software distributed under the License is distributed on an
+-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-- KIND, either express or implied. See the License for the
+-- specific language governing permissions and limitations
+-- under the License.
+
+--;
+-- Schema upgrade cleanup from 4.10.0.0 to 4.11.0.0
+--;
+
+DELETE FROM `cloud`.`configuration` WHERE name='snapshot.backup.rightafter';
+-- CLOUDSTACK-9914: Alter quota_tariff to support currency values up to 5 decimal places
+ALTER TABLE `cloud_usage`.`quota_tariff` MODIFY `currency_value` DECIMAL(15,5) not null
diff --git a/setup/db/db/schema-41000to41100.sql b/setup/db/db/schema-41000to41100.sql
new file mode 100644
index 00000000000..e5e6c0552ee
--- /dev/null
+++ b/setup/db/db/schema-41000to41100.sql
@@ -0,0 +1,298 @@
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements. See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership. The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing,
+-- software distributed under the License is distributed on an
+-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-- KIND, either express or implied. See the License for the
+-- specific language governing permissions and limitations
+-- under the License.
+
+--;
+-- Schema upgrade from 4.10.0.0 to 4.11.0.0
+--;
+
+--Alter view template_view
+
+DROP VIEW IF EXISTS `cloud`.`template_view`;
+CREATE VIEW `template_view` AS
+ SELECT
+ `vm_template`.`id` AS `id`,
+ `vm_template`.`uuid` AS `uuid`,
+ `vm_template`.`unique_name` AS `unique_name`,
+ `vm_template`.`name` AS `name`,
+ `vm_template`.`public` AS `public`,
+ `vm_template`.`featured` AS `featured`,
+ `vm_template`.`type` AS `type`,
+ `vm_template`.`hvm` AS `hvm`,
+ `vm_template`.`bits` AS `bits`,
+ `vm_template`.`url` AS `url`,
+ `vm_template`.`format` AS `format`,
+ `vm_template`.`created` AS `created`,
+ `vm_template`.`checksum` AS `checksum`,
+ `vm_template`.`display_text` AS `display_text`,
+ `vm_template`.`enable_password` AS `enable_password`,
+ `vm_template`.`dynamically_scalable` AS `dynamically_scalable`,
+ `vm_template`.`state` AS `template_state`,
+ `vm_template`.`guest_os_id` AS `guest_os_id`,
+ `guest_os`.`uuid` AS `guest_os_uuid`,
+ `guest_os`.`display_name` AS `guest_os_name`,
+ `vm_template`.`bootable` AS `bootable`,
+ `vm_template`.`prepopulate` AS `prepopulate`,
+ `vm_template`.`cross_zones` AS `cross_zones`,
+ `vm_template`.`hypervisor_type` AS `hypervisor_type`,
+ `vm_template`.`extractable` AS `extractable`,
+ `vm_template`.`template_tag` AS `template_tag`,
+ `vm_template`.`sort_key` AS `sort_key`,
+ `vm_template`.`removed` AS `removed`,
+ `vm_template`.`enable_sshkey` AS `enable_sshkey`,
+ `source_template`.`id` AS `source_template_id`,
+ `source_template`.`uuid` AS `source_template_uuid`,
+ `account`.`id` AS `account_id`,
+ `account`.`uuid` AS `account_uuid`,
+ `account`.`account_name` AS `account_name`,
+ `account`.`type` AS `account_type`,
+ `domain`.`id` AS `domain_id`,
+ `domain`.`uuid` AS `domain_uuid`,
+ `domain`.`name` AS `domain_name`,
+ `domain`.`path` AS `domain_path`,
+ `projects`.`id` AS `project_id`,
+ `projects`.`uuid` AS `project_uuid`,
+ `projects`.`name` AS `project_name`,
+ `data_center`.`id` AS `data_center_id`,
+ `data_center`.`uuid` AS `data_center_uuid`,
+ `data_center`.`name` AS `data_center_name`,
+ `launch_permission`.`account_id` AS `lp_account_id`,
+ `template_store_ref`.`store_id` AS `store_id`,
+ `image_store`.`scope` AS `store_scope`,
+ `template_store_ref`.`state` AS `state`,
+ `template_store_ref`.`download_state` AS `download_state`,
+ `template_store_ref`.`download_pct` AS `download_pct`,
+ `template_store_ref`.`error_str` AS `error_str`,
+ `template_store_ref`.`size` AS `size`,
+ `template_store_ref`.physical_size AS `physical_size`,
+ `template_store_ref`.`destroyed` AS `destroyed`,
+ `template_store_ref`.`created` AS `created_on_store`,
+ `vm_template_details`.`name` AS `detail_name`,
+ `vm_template_details`.`value` AS `detail_value`,
+ `resource_tags`.`id` AS `tag_id`,
+ `resource_tags`.`uuid` AS `tag_uuid`,
+ `resource_tags`.`key` AS `tag_key`,
+ `resource_tags`.`value` AS `tag_value`,
+ `resource_tags`.`domain_id` AS `tag_domain_id`,
+ `domain`.`uuid` AS `tag_domain_uuid`,
+ `domain`.`name` AS `tag_domain_name`,
+ `resource_tags`.`account_id` AS `tag_account_id`,
+ `account`.`account_name` AS `tag_account_name`,
+ `resource_tags`.`resource_id` AS `tag_resource_id`,
+ `resource_tags`.`resource_uuid` AS `tag_resource_uuid`,
+ `resource_tags`.`resource_type` AS `tag_resource_type`,
+ `resource_tags`.`customer` AS `tag_customer`,
+ CONCAT(`vm_template`.`id`,
+ '_',
+ IFNULL(`data_center`.`id`, 0)) AS `temp_zone_pair`
+ FROM
+ ((((((((((((`vm_template`
+ JOIN `guest_os` ON ((`guest_os`.`id` = `vm_template`.`guest_os_id`)))
+ JOIN `account` ON ((`account`.`id` = `vm_template`.`account_id`)))
+ JOIN `domain` ON ((`domain`.`id` = `account`.`domain_id`)))
+ LEFT JOIN `projects` ON ((`projects`.`project_account_id` = `account`.`id`)))
+ LEFT JOIN `vm_template_details` ON ((`vm_template_details`.`template_id` = `vm_template`.`id`)))
+ LEFT JOIN `vm_template` `source_template` ON ((`source_template`.`id` = `vm_template`.`source_template_id`)))
+ LEFT JOIN `template_store_ref` ON (((`template_store_ref`.`template_id` = `vm_template`.`id`)
+ AND (`template_store_ref`.`store_role` = 'Image')
+ AND (`template_store_ref`.`destroyed` = 0))))
+ LEFT JOIN `image_store` ON ((ISNULL(`image_store`.`removed`)
+ AND (`template_store_ref`.`store_id` IS NOT NULL)
+ AND (`image_store`.`id` = `template_store_ref`.`store_id`))))
+ LEFT JOIN `template_zone_ref` ON (((`template_zone_ref`.`template_id` = `vm_template`.`id`)
+ AND ISNULL(`template_store_ref`.`store_id`)
+ AND ISNULL(`template_zone_ref`.`removed`))))
+ LEFT JOIN `data_center` ON (((`image_store`.`data_center_id` = `data_center`.`id`)
+ OR (`template_zone_ref`.`zone_id` = `data_center`.`id`))))
+ LEFT JOIN `launch_permission` ON ((`launch_permission`.`template_id` = `vm_template`.`id`)))
+ LEFT JOIN `resource_tags` ON (((`resource_tags`.`resource_id` = `vm_template`.`id`)
+ AND ((`resource_tags`.`resource_type` = 'Template')
+ OR (`resource_tags`.`resource_type` = 'ISO')))));
+
+UPDATE `cloud`.`configuration` SET value = '600', default_value = '600' WHERE category = 'Advanced' AND name = 'router.aggregation.command.each.timeout';
+
+-- CA framework changes
+DELETE from `cloud`.`configuration` where name='ssl.keystore';
+
+-- Certificate Revocation List
+CREATE TABLE IF NOT EXISTS `cloud`.`crl` (
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `serial` varchar(255) UNIQUE NOT NULL COMMENT 'certificate\'s serial number as hex string',
+ `cn` varchar(255) COMMENT 'certificate\'s common name',
+ `revoker_uuid` varchar(40) COMMENT 'revoker user account uuid',
+ `revoked` datetime COMMENT 'date of revocation',
+ PRIMARY KEY (`id`),
+ KEY (`serial`),
+ UNIQUE KEY (`serial`, `cn`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- Host HA feature
+CREATE TABLE IF NOT EXISTS `cloud`.`ha_config` (
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `resource_id` bigint(20) unsigned DEFAULT NULL COMMENT 'id of the resource',
+ `resource_type` varchar(255) NOT NULL COMMENT 'the type of the resource',
+ `enabled` int(1) unsigned DEFAULT '0' COMMENT 'is HA enabled for the resource',
+ `ha_state` varchar(255) DEFAULT 'Disabled' COMMENT 'HA state',
+ `provider` varchar(255) DEFAULT NULL COMMENT 'HA provider',
+ `update_count` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT 'state based incr-only counter for atomic ha_state updates',
+ `update_time` datetime COMMENT 'last ha_state update datetime',
+ `mgmt_server_id` bigint(20) unsigned DEFAULT NULL COMMENT 'management server id that is responsible for the HA for the resource',
+ PRIMARY KEY (`id`),
+ KEY `i_ha_config__enabled` (`enabled`),
+ KEY `i_ha_config__ha_state` (`ha_state`),
+ KEY `i_ha_config__mgmt_server_id` (`mgmt_server_id`),
+ UNIQUE KEY (`resource_id`, `resource_type`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+DELETE from `cloud`.`configuration` where name='outofbandmanagement.sync.interval';
+
+-- Annotations specifc changes following
+CREATE TABLE IF NOT EXISTS `cloud`.`annotations` (
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `uuid` varchar(40) UNIQUE,
+ `annotation` text,
+ `entity_uuid` varchar(40),
+ `entity_type` varchar(32),
+ `user_uuid` varchar(40),
+ `created` datetime COMMENT 'date of creation',
+ `removed` datetime COMMENT 'date of removal',
+ PRIMARY KEY (`id`),
+ KEY (`uuid`),
+ KEY `i_entity` (`entity_uuid`, `entity_type`, `created`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+DROP VIEW IF EXISTS `cloud`.`last_annotation_view`;
+CREATE VIEW `last_annotation_view` AS
+ SELECT
+ `annotations`.`uuid` AS `uuid`,
+ `annotations`.`annotation` AS `annotation`,
+ `annotations`.`entity_uuid` AS `entity_uuid`,
+ `annotations`.`entity_type` AS `entity_type`,
+ `annotations`.`user_uuid` AS `user_uuid`,
+ `annotations`.`created` AS `created`,
+ `annotations`.`removed` AS `removed`
+ FROM
+ `annotations`
+ WHERE
+ `annotations`.`created` IN (SELECT
+ MAX(`annotations`.`created`)
+ FROM
+ `annotations`
+ WHERE
+ `annotations`.`removed` IS NULL
+ GROUP BY `annotations`.`entity_uuid`);
+
+-- Host HA changes:
+DROP VIEW IF EXISTS `cloud`.`host_view`;
+CREATE VIEW `cloud`.`host_view` AS
+ SELECT
+ host.id,
+ host.uuid,
+ host.name,
+ host.status,
+ host.disconnected,
+ host.type,
+ host.private_ip_address,
+ host.version,
+ host.hypervisor_type,
+ host.hypervisor_version,
+ host.capabilities,
+ host.last_ping,
+ host.created,
+ host.removed,
+ host.resource_state,
+ host.mgmt_server_id,
+ host.cpu_sockets,
+ host.cpus,
+ host.speed,
+ host.ram,
+ cluster.id cluster_id,
+ cluster.uuid cluster_uuid,
+ cluster.name cluster_name,
+ cluster.cluster_type,
+ data_center.id data_center_id,
+ data_center.uuid data_center_uuid,
+ data_center.name data_center_name,
+ data_center.networktype data_center_type,
+ host_pod_ref.id pod_id,
+ host_pod_ref.uuid pod_uuid,
+ host_pod_ref.name pod_name,
+ host_tags.tag,
+ guest_os_category.id guest_os_category_id,
+ guest_os_category.uuid guest_os_category_uuid,
+ guest_os_category.name guest_os_category_name,
+ mem_caps.used_capacity memory_used_capacity,
+ mem_caps.reserved_capacity memory_reserved_capacity,
+ cpu_caps.used_capacity cpu_used_capacity,
+ cpu_caps.reserved_capacity cpu_reserved_capacity,
+ async_job.id job_id,
+ async_job.uuid job_uuid,
+ async_job.job_status job_status,
+ async_job.account_id job_account_id,
+ oobm.enabled AS `oobm_enabled`,
+ oobm.power_state AS `oobm_power_state`,
+ ha_config.enabled AS `ha_enabled`,
+ ha_config.ha_state AS `ha_state`,
+ ha_config.provider AS `ha_provider`,
+ `last_annotation_view`.`annotation` AS `annotation`,
+ `last_annotation_view`.`created` AS `last_annotated`,
+ `user`.`username` AS `username`
+ FROM
+ `cloud`.`host`
+ LEFT JOIN
+ `cloud`.`cluster` ON host.cluster_id = cluster.id
+ LEFT JOIN
+ `cloud`.`data_center` ON host.data_center_id = data_center.id
+ LEFT JOIN
+ `cloud`.`host_pod_ref` ON host.pod_id = host_pod_ref.id
+ LEFT JOIN
+ `cloud`.`host_details` ON host.id = host_details.host_id
+ AND host_details.name = 'guest.os.category.id'
+ LEFT JOIN
+ `cloud`.`guest_os_category` ON guest_os_category.id = CONVERT ( host_details.value, UNSIGNED )
+ LEFT JOIN
+ `cloud`.`host_tags` ON host_tags.host_id = host.id
+ LEFT JOIN
+ `cloud`.`op_host_capacity` mem_caps ON host.id = mem_caps.host_id
+ AND mem_caps.capacity_type = 0
+ LEFT JOIN
+ `cloud`.`op_host_capacity` cpu_caps ON host.id = cpu_caps.host_id
+ AND cpu_caps.capacity_type = 1
+ LEFT JOIN
+ `cloud`.`async_job` ON async_job.instance_id = host.id
+ AND async_job.instance_type = 'Host'
+ AND async_job.job_status = 0
+ LEFT JOIN
+ `cloud`.`oobm` ON oobm.host_id = host.id
+ left join
+ `cloud`.`ha_config` ON ha_config.resource_id=host.id
+ and ha_config.resource_type='Host'
+ LEFT JOIN
+ `cloud`.`last_annotation_view` ON `last_annotation_view`.`entity_uuid` = `host`.`uuid`
+ LEFT JOIN
+ `cloud`.`user` ON `user`.`uuid` = `last_annotation_view`.`user_uuid`;
+-- End Of Annotations specific changes
+
+
+-- Out-of-band management driver for nested-cloudstack
+ALTER TABLE `cloud`.`oobm` MODIFY COLUMN port VARCHAR(255);
+
+
+-- CLOUDSTACK-9902: Console proxy SSL toggle
+INSERT IGNORE INTO `cloud`.`configuration` (`category`, `instance`, `component`, `name`, `value`, `description`, `default_value`, `is_dynamic`) VALUES ('Console Proxy', 'DEFAULT', 'AgentManager', 'consoleproxy.sslEnabled', 'false', 'Enable SSL for console proxy', 'false', 0);
+
+-- CLOUDSTACK-9859: Retirement of midonet plugin (final removal)
+delete from `cloud`.`configuration` where name in ('midonet.apiserver.address', 'midonet.providerrouter.id');
\ No newline at end of file
diff --git a/setup/db/db/schema-480to481.sql b/setup/db/db/schema-480to481.sql
index 3b2d40b3d82..4c8637bbd6a 100644
--- a/setup/db/db/schema-480to481.sql
+++ b/setup/db/db/schema-480to481.sql
@@ -18,3 +18,4 @@
--;
-- Schema upgrade from 4.8.0 to 4.8.1;
--;
+
diff --git a/setup/db/db/schema-481to490-cleanup.sql b/setup/db/db/schema-481to490-cleanup.sql
index 0ab02d83089..adf566e07fe 100644
--- a/setup/db/db/schema-481to490-cleanup.sql
+++ b/setup/db/db/schema-481to490-cleanup.sql
@@ -272,79 +272,3 @@ CREATE VIEW `cloud`.`user_view` AS
and async_job.instance_type = 'User'
and async_job.job_status = 0;
--- Out-of-band management
-DROP VIEW IF EXISTS `cloud`.`host_view`;
-CREATE VIEW `cloud`.`host_view` AS
- select
- host.id,
- host.uuid,
- host.name,
- host.status,
- host.disconnected,
- host.type,
- host.private_ip_address,
- host.version,
- host.hypervisor_type,
- host.hypervisor_version,
- host.capabilities,
- host.last_ping,
- host.created,
- host.removed,
- host.resource_state,
- host.mgmt_server_id,
- host.cpu_sockets,
- host.cpus,
- host.speed,
- host.ram,
- cluster.id cluster_id,
- cluster.uuid cluster_uuid,
- cluster.name cluster_name,
- cluster.cluster_type,
- data_center.id data_center_id,
- data_center.uuid data_center_uuid,
- data_center.name data_center_name,
- data_center.networktype data_center_type,
- host_pod_ref.id pod_id,
- host_pod_ref.uuid pod_uuid,
- host_pod_ref.name pod_name,
- host_tags.tag,
- guest_os_category.id guest_os_category_id,
- guest_os_category.uuid guest_os_category_uuid,
- guest_os_category.name guest_os_category_name,
- mem_caps.used_capacity memory_used_capacity,
- mem_caps.reserved_capacity memory_reserved_capacity,
- cpu_caps.used_capacity cpu_used_capacity,
- cpu_caps.reserved_capacity cpu_reserved_capacity,
- async_job.id job_id,
- async_job.uuid job_uuid,
- async_job.job_status job_status,
- async_job.account_id job_account_id,
- oobm.enabled AS `oobm_enabled`,
- oobm.power_state AS `oobm_power_state`
- from
- `cloud`.`host`
- left join
- `cloud`.`cluster` ON host.cluster_id = cluster.id
- left join
- `cloud`.`data_center` ON host.data_center_id = data_center.id
- left join
- `cloud`.`host_pod_ref` ON host.pod_id = host_pod_ref.id
- left join
- `cloud`.`host_details` ON host.id = host_details.host_id
- and host_details.name = 'guest.os.category.id'
- left join
- `cloud`.`guest_os_category` ON guest_os_category.id = CONVERT( host_details.value , UNSIGNED)
- left join
- `cloud`.`host_tags` ON host_tags.host_id = host.id
- left join
- `cloud`.`op_host_capacity` mem_caps ON host.id = mem_caps.host_id
- and mem_caps.capacity_type = 0
- left join
- `cloud`.`op_host_capacity` cpu_caps ON host.id = cpu_caps.host_id
- and cpu_caps.capacity_type = 1
- left join
- `cloud`.`async_job` ON async_job.instance_id = host.id
- and async_job.instance_type = 'Host'
- and async_job.job_status = 0
- left join
- `cloud`.`oobm` ON oobm.host_id = host.id;
diff --git a/setup/db/db/schema-481to490.sql b/setup/db/db/schema-481to490.sql
index 7f33043146e..49cfc8346c5 100644
--- a/setup/db/db/schema-481to490.sql
+++ b/setup/db/db/schema-481to490.sql
@@ -495,6 +495,83 @@ CREATE TABLE IF NOT EXISTS `cloud`.`oobm` (
CONSTRAINT `fk_oobm__host_id` FOREIGN KEY (`host_id`) REFERENCES `host` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+-- Out-of-band management
+DROP VIEW IF EXISTS `cloud`.`host_view`;
+CREATE VIEW `cloud`.`host_view` AS
+ select
+ host.id,
+ host.uuid,
+ host.name,
+ host.status,
+ host.disconnected,
+ host.type,
+ host.private_ip_address,
+ host.version,
+ host.hypervisor_type,
+ host.hypervisor_version,
+ host.capabilities,
+ host.last_ping,
+ host.created,
+ host.removed,
+ host.resource_state,
+ host.mgmt_server_id,
+ host.cpu_sockets,
+ host.cpus,
+ host.speed,
+ host.ram,
+ cluster.id cluster_id,
+ cluster.uuid cluster_uuid,
+ cluster.name cluster_name,
+ cluster.cluster_type,
+ data_center.id data_center_id,
+ data_center.uuid data_center_uuid,
+ data_center.name data_center_name,
+ data_center.networktype data_center_type,
+ host_pod_ref.id pod_id,
+ host_pod_ref.uuid pod_uuid,
+ host_pod_ref.name pod_name,
+ host_tags.tag,
+ guest_os_category.id guest_os_category_id,
+ guest_os_category.uuid guest_os_category_uuid,
+ guest_os_category.name guest_os_category_name,
+ mem_caps.used_capacity memory_used_capacity,
+ mem_caps.reserved_capacity memory_reserved_capacity,
+ cpu_caps.used_capacity cpu_used_capacity,
+ cpu_caps.reserved_capacity cpu_reserved_capacity,
+ async_job.id job_id,
+ async_job.uuid job_uuid,
+ async_job.job_status job_status,
+ async_job.account_id job_account_id,
+ oobm.enabled AS `oobm_enabled`,
+ oobm.power_state AS `oobm_power_state`
+ from
+ `cloud`.`host`
+ left join
+ `cloud`.`cluster` ON host.cluster_id = cluster.id
+ left join
+ `cloud`.`data_center` ON host.data_center_id = data_center.id
+ left join
+ `cloud`.`host_pod_ref` ON host.pod_id = host_pod_ref.id
+ left join
+ `cloud`.`host_details` ON host.id = host_details.host_id
+ and host_details.name = 'guest.os.category.id'
+ left join
+ `cloud`.`guest_os_category` ON guest_os_category.id = CONVERT( host_details.value , UNSIGNED)
+ left join
+ `cloud`.`host_tags` ON host_tags.host_id = host.id
+ left join
+ `cloud`.`op_host_capacity` mem_caps ON host.id = mem_caps.host_id
+ and mem_caps.capacity_type = 0
+ left join
+ `cloud`.`op_host_capacity` cpu_caps ON host.id = cpu_caps.host_id
+ and cpu_caps.capacity_type = 1
+ left join
+ `cloud`.`async_job` ON async_job.instance_id = host.id
+ and async_job.instance_type = 'Host'
+ and async_job.job_status = 0
+ left join
+ `cloud`.`oobm` ON oobm.host_id = host.id;
+
INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(), 'VMware', '4.0', 'centosGuest', 171, now(), 0);
INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(), 'VMware', '4.1', 'centosGuest', 171, now(), 0);
INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(), 'VMware', '5.0', 'centosGuest', 171, now(), 0);
@@ -545,4 +622,3 @@ INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervis
INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(), 'VMware', '5.0', 'centos64Guest', 228, now(), 0);
INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(), 'VMware', '5.1', 'centos64Guest', 228, now(), 0);
INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(), 'VMware', '5.5', 'centos64Guest', 228, now(), 0);
-
diff --git a/setup/db/db/schema-4930to41000-cleanup.sql b/setup/db/db/schema-4930to41000-cleanup.sql
index 986dcdfe7da..c1791890e3a 100644
--- a/setup/db/db/schema-4930to41000-cleanup.sql
+++ b/setup/db/db/schema-4930to41000-cleanup.sql
@@ -22,3 +22,48 @@
DELETE FROM `cloud`.`configuration` WHERE name='consoleproxy.loadscan.interval';
DELETE FROM `cloud`.`host_details` where name = 'vmName' and value in (select name from `cloud`.`vm_instance` where state = 'Expunging' and hypervisor_type ='BareMetal');
+
+DROP VIEW IF EXISTS `cloud`.`user_view`;
+CREATE VIEW `cloud`.`user_view` AS
+ select
+ user.id,
+ user.uuid,
+ user.username,
+ user.password,
+ user.firstname,
+ user.lastname,
+ user.email,
+ user.state,
+ user.api_key,
+ user.secret_key,
+ user.created,
+ user.removed,
+ user.timezone,
+ user.registration_token,
+ user.is_registered,
+ user.incorrect_login_attempts,
+ user.source,
+ user.default,
+ account.id account_id,
+ account.uuid account_uuid,
+ account.account_name account_name,
+ account.type account_type,
+ account.role_id account_role_id,
+ domain.id domain_id,
+ domain.uuid domain_uuid,
+ domain.name domain_name,
+ domain.path domain_path,
+ async_job.id job_id,
+ async_job.uuid job_uuid,
+ async_job.job_status job_status,
+ async_job.account_id job_account_id
+ from
+ `cloud`.`user`
+ inner join
+ `cloud`.`account` ON user.account_id = account.id
+ inner join
+ `cloud`.`domain` ON account.domain_id = domain.id
+ left join
+ `cloud`.`async_job` ON async_job.instance_id = user.id
+ and async_job.instance_type = 'User'
+ and async_job.job_status = 0;
diff --git a/setup/db/db/schema-4930to41000.sql b/setup/db/db/schema-4930to41000.sql
index 59c452fba63..db4e8605580 100644
--- a/setup/db/db/schema-4930to41000.sql
+++ b/setup/db/db/schema-4930to41000.sql
@@ -254,4 +254,27 @@ CREATE TABLE `cloud`.`firewall_rules_dcidrs`(
UNIQUE KEY `unique_rule_dcidrs` (`firewall_rule_id`, `destination_cidr`),
KEY `fk_firewall_dcidrs_firewall_rules` (`firewall_rule_id`),
CONSTRAINT `fk_firewall_dcidrs_firewall_rules` FOREIGN KEY (`firewall_rule_id`) REFERENCES `firewall_rules` (`id`) ON DELETE CASCADE
-)ENGINE=InnoDB DEFAULT CHARSET=utf8;
\ No newline at end of file
+)ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+DROP TABLE IF EXISTS `cloud`.`netscaler_servicepackages`;
+CREATE TABLE `cloud`.`netscaler_servicepackages` (
+ `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
+ `uuid` varchar(255) UNIQUE,
+ `name` varchar(255) UNIQUE COMMENT 'name of the service package',
+ `description` varchar(255) COMMENT 'description of the service package',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+DROP TABLE IF EXISTS `cloud`.`external_netscaler_controlcenter`;
+CREATE TABLE `cloud`.`external_netscaler_controlcenter` (
+ `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
+ `uuid` varchar(255) UNIQUE,
+ `username` varchar(255) COMMENT 'username of the NCC',
+ `password` varchar(255) COMMENT 'password of NCC',
+ `ncc_ip` varchar(255) COMMENT 'IP of NCC Manager',
+ `num_retries` bigint unsigned NOT NULL default 2 COMMENT 'Number of retries in ncc for command failure',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+ALTER TABLE `cloud`.`sslcerts` ADD COLUMN `name` varchar(255) NULL default NULL COMMENT 'Name of the Certificate';
+ALTER TABLE `cloud`.`network_offerings` ADD COLUMN `service_package_id` varchar(255) NULL default NULL COMMENT 'Netscaler ControlCenter Service Package';
diff --git a/setup/db/server-setup.sql b/setup/db/server-setup.sql
index df2c9248552..1c4635c72ca 100644
--- a/setup/db/server-setup.sql
+++ b/setup/db/server-setup.sql
@@ -27,3 +27,6 @@ INSERT INTO `cloud`.`configuration` (category, instance, component, name, value,
-- Enable dynamic RBAC by default for fresh deployments
INSERT INTO `cloud`.`configuration` (category, instance, component, name, value) VALUES ('Advanced', 'DEFAULT', 'RoleService', 'dynamic.apichecker.enabled', 'true');
+
+-- Enable RootCA auth strictness for fresh deployments
+INSERT INTO `cloud`.`configuration` (category, instance, component, name, value) VALUES ('Advanced', 'DEFAULT', 'RootCAProvider', 'ca.plugin.root.auth.strictness', 'true');
diff --git a/setup/db/server-setup.xml b/setup/db/server-setup.xml
index 178f29aea35..955a3a51806 100755
--- a/setup/db/server-setup.xml
+++ b/setup/db/server-setup.xml
@@ -246,6 +246,13 @@ under the License.
<value>true</value>
</configuration>
<!--
+ Enable RootCA auth strictness for fresh installations
+ -->
+ <configuration>
+ <name>ca.plugin.root.auth.strictness</name>
+ <value>true</value>
+ </configuration>
+ <!--
The instance.name parameter is tacked to the end of the names of the VMs you create.
So, for example, with the TEST value as it ships by default, your VMs would be named:
i-X-Y-TEST, where X is the account ID and Y is the serially incrementing VM ID.
diff --git a/setup/dev/advanced.cfg b/setup/dev/advanced.cfg
index 0742f2468ee..bdb25e56456 100644
--- a/setup/dev/advanced.cfg
+++ b/setup/dev/advanced.cfg
@@ -113,6 +113,11 @@
"username": "root",
"url": "http://sim/c1/h0",
"password": "password"
+ },
+ {
+ "username": "root",
+ "url": "http://sim/c1/h1",
+ "password": "password"
}
],
"clustertype": "CloudManaged",
@@ -120,6 +125,10 @@
{
"url": "nfs://10.147.28.6:/export/home/sandbox/primary2",
"name": "PS2"
+ },
+ {
+ "url": "nfs://10.147.28.6:/export/home/sandbox/primary3",
+ "name": "PS2"
}
]
}
@@ -223,10 +232,6 @@
{
"name": "ping.timeout",
"value": "1.5"
- },
- {
- "name": "outofbandmanagement.sync.interval",
- "value": "1000"
}
],
"mgtSvr": [
diff --git a/systemvm/js/ajaxviewer.js b/systemvm/js/ajaxviewer.js
index 09fb41a7399..f8554a5f7ec 100644
--- a/systemvm/js/ajaxviewer.js
+++ b/systemvm/js/ajaxviewer.js
@@ -617,6 +617,7 @@ AjaxViewer.prototype = {
var img = $(this.img);
this.fullImage = fullImage;
this.imgUrl=imageUrl;
+ this.imageLoaded = false;
img.attr('src', imageUrl).load(function() {
ajaxViewer.imageLoaded = true;
diff --git a/systemvm/patches/debian/config/etc/init.d/cloud-early-config b/systemvm/patches/debian/config/etc/init.d/cloud-early-config
index ac54ebfd1fb..3bdebdbb798 100755
--- a/systemvm/patches/debian/config/etc/init.d/cloud-early-config
+++ b/systemvm/patches/debian/config/etc/init.d/cloud-early-config
@@ -1032,6 +1032,7 @@ EOF
enable_irqbalance 1
enable_vpc_rpsrfs 1
enable_svc cloud 0
+ enable_svc cloud-passwd-srvr 1
disable_rpfilter
enable_fwding 1
cp /etc/iptables/iptables-vpcrouter /etc/iptables/rules.v4
diff --git a/systemvm/patches/debian/config/opt/cloud/bin/configure.py b/systemvm/patches/debian/config/opt/cloud/bin/configure.py
index a39e10baa29..f1113098137 100755
--- a/systemvm/patches/debian/config/opt/cloud/bin/configure.py
+++ b/systemvm/patches/debian/config/opt/cloud/bin/configure.py
@@ -892,7 +892,7 @@ def forward_vr(self, rule):
self.fw.append(["filter", "", fw7])
def forward_vpc(self, rule):
- fw_prerout_rule = "-A PREROUTING -d %s/32 -i %s" % (rule["public_ip"], self.getDeviceByIp(rule['public_ip']))
+ fw_prerout_rule = "-A PREROUTING -d %s/32 " % (rule["public_ip"])
if not rule["protocol"] == "any":
fw_prerout_rule += " -m %s -p %s" % (rule["protocol"], rule["protocol"])
if not rule["public_ports"] == "any":
@@ -928,12 +928,13 @@ def processStaticNatRule(self, rule):
device = self.getDeviceByIp(rule["public_ip"])
if device is None:
raise Exception("Ip address %s has no device in the ips databag" % rule["public_ip"])
+
self.fw.append(["mangle", "",
- "-A PREROUTING -s %s/32 -m state --state NEW -j MARK --set-xmark 0x%s/0xffffffff" % \
- (rule["internal_ip"], device[len("eth"):])])
- self.fw.append(["mangle", "",
- "-A PREROUTING -s %s/32 -m state --state NEW -j CONNMARK --save-mark --nfmask 0xffffffff --ctmask 0xffffffff" % \
+ "-I PREROUTING -s %s/32 -m state --state NEW -j CONNMARK --save-mark --nfmask 0xffffffff --ctmask 0xffffffff" % \
rule["internal_ip"]])
+ self.fw.append(["mangle", "",
+ "-I PREROUTING -s %s/32 -m state --state NEW -j MARK --set-xmark 0x%s/0xffffffff" % \
+ (rule["internal_ip"], device[len("eth"):])])
self.fw.append(["nat", "front",
"-A PREROUTING -d %s/32 -j DNAT --to-destination %s" % (rule["public_ip"], rule["internal_ip"])])
self.fw.append(["nat", "front",
diff --git a/systemvm/patches/debian/config/opt/cloud/bin/merge.py b/systemvm/patches/debian/config/opt/cloud/bin/merge.py
index 9c9b42a1393..1c9adf26f5e 100755
--- a/systemvm/patches/debian/config/opt/cloud/bin/merge.py
+++ b/systemvm/patches/debian/config/opt/cloud/bin/merge.py
@@ -151,7 +151,7 @@ def processGuestNetwork(self, dbag):
dp['add'] = d['add']
dp['one_to_one_nat'] = False
dp['gateway'] = d['router_guest_gateway']
- dp['nic_dev_id'] = d['device'][3]
+ dp['nic_dev_id'] = d['device'][3:]
dp['nw_type'] = 'guest'
dp = PrivateGatewayHack.update_network_type_for_privategateway(dbag, dp)
qf = QueueFile()
diff --git a/systemvm/patches/debian/config/opt/cloud/bin/passwd_server_ip b/systemvm/patches/debian/config/opt/cloud/bin/passwd_server_ip
index a408a1e5bee..5e15a19ad82 100755
--- a/systemvm/patches/debian/config/opt/cloud/bin/passwd_server_ip
+++ b/systemvm/patches/debian/config/opt/cloud/bin/passwd_server_ip
@@ -18,7 +18,6 @@
. /etc/default/cloud-passwd-srvr
addr=$1;
-ENABLED=1
while [ "$ENABLED" == "1" ]
do
python /opt/cloud/bin/passwd_server_ip.py $addr >/dev/null 2>/dev/null
diff --git a/systemvm/patches/debian/config/opt/cloud/bin/patchsystemvm.sh b/systemvm/patches/debian/config/opt/cloud/bin/patchsystemvm.sh
index 9a47f8eac27..34450dc08ca 100755
--- a/systemvm/patches/debian/config/opt/cloud/bin/patchsystemvm.sh
+++ b/systemvm/patches/debian/config/opt/cloud/bin/patchsystemvm.sh
@@ -16,19 +16,26 @@
# specific language governing permissions and limitations
# under the License.
-
-
-# $Id: patchsystemvm.sh 10800 2010-07-16 13:48:39Z edison $ $HeadURL: svn://svn.lab.vmops.com/repos/branches/2.1.x/java/scripts/vm/hypervisor/xenserver/prepsystemvm.sh $
-
#set -x
logfile="/var/log/patchsystemvm.log"
# To use existing console proxy .zip-based package file
patch_console_proxy() {
local patchfile=$1
+ local backupfolder="/tmp/.conf.backup"
+ if [ -f /usr/local/cloud/systemvm/conf/cloud.jks ]; then
+ rm -fr $backupfolder
+ mkdir -p $backupfolder
+ cp -r /usr/local/cloud/systemvm/conf/* $backupfolder/
+ fi
rm /usr/local/cloud/systemvm -rf
mkdir -p /usr/local/cloud/systemvm
echo "All" | unzip $patchfile -d /usr/local/cloud/systemvm >$logfile 2>&1
find /usr/local/cloud/systemvm/ -name \*.sh | xargs chmod 555
+ if [ -f $backupfolder/cloud.jks ]; then
+ cp -r $backupfolder/* /usr/local/cloud/systemvm/conf/
+ echo "Restored keystore file and certs using backup" >> $logfile
+ fi
+ rm -fr $backupfolder
return 0
}
diff --git a/systemvm/pom.xml b/systemvm/pom.xml
index 80055b86cba..4d657b72274 100644
--- a/systemvm/pom.xml
+++ b/systemvm/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<properties>
@@ -125,6 +125,11 @@
<exclude name="**/xen-*" />
</fileset>
</copy>
+ <copy overwrite="true" todir="${basedir}/target/build-patch/opt/cloud/bin/">
+ <fileset dir="${basedir}/../scripts/util/">
+ <include name="**/keystore-*" />
+ </fileset>
+ </copy>
<copy overwrite="true" todir="${basedir}/target/build-patch/usr/sbin/">
<fileset dir="${basedir}/patches/debian/xe/">
<include name="**/xe-*" />
diff --git a/systemvm/scripts/_run.sh b/systemvm/scripts/_run.sh
index 3792261c143..6d77002b8c4 100755
--- a/systemvm/scripts/_run.sh
+++ b/systemvm/scripts/_run.sh
@@ -68,4 +68,4 @@ if [ "$(uname -m | grep '64')" == "" ]; then
fi
fi
-java -Djavax.net.ssl.trustStore=./certs/realhostip.keystore -Djsse.enableSNIExtension=false -Dlog.home=$LOGHOME -mx${maxmem}m -cp $CP com.cloud.agent.AgentShell $keyvalues $@
+java -Djavax.net.ssl.trustStore=./certs/realhostip.keystore -Djdk.tls.ephemeralDHKeySize=2048 -Djsse.enableSNIExtension=false -Dlog.home=$LOGHOME -mx${maxmem}m -cp $CP com.cloud.agent.AgentShell $keyvalues $@
diff --git a/systemvm/scripts/config_ssl.sh b/systemvm/scripts/config_ssl.sh
index 86358871c9c..3aeb9455c46 100755
--- a/systemvm/scripts/config_ssl.sh
+++ b/systemvm/scripts/config_ssl.sh
@@ -120,7 +120,7 @@ customCACert=
publicIp=
hostName=
keyStore=$(dirname $0)/certs/realhostip.keystore
-defaultJavaKeyStoreFile=/etc/ssl/certs/java/cacerts
+defaultJavaKeyStoreFile="$(jrunscript -e 'java.lang.System.out.println(java.lang.System.getProperty("java.home"));')/lib/security/cacerts"
defaultJavaKeyStorePass="changeit"
aliasName="CPVMCertificate"
storepass="vmops.com"
diff --git a/systemvm/systemvm-descriptor.xml b/systemvm/systemvm-descriptor.xml
index 1a943b0509e..eec916e86fc 100644
--- a/systemvm/systemvm-descriptor.xml
+++ b/systemvm/systemvm-descriptor.xml
@@ -30,6 +30,15 @@
</dependencySet>
</dependencySets>
<fileSets>
+ <fileSet>
+ <directory>../scripts/util/</directory>
+ <outputDirectory>scripts/util</outputDirectory>
+ <directoryMode>555</directoryMode>
+ <fileMode>555</fileMode>
+ <includes>
+ <include>keystore*</include>
+ </includes>
+ </fileSet>
<fileSet>
<directory>../scripts/storage/secondary/</directory>
<outputDirectory>scripts/storage/secondary</outputDirectory>
diff --git a/test/integration/component/test_accounts.py b/test/integration/component/test_accounts.py
index 60421d9eab7..a64d922e956 100644
--- a/test/integration/component/test_accounts.py
+++ b/test/integration/component/test_accounts.py
@@ -20,6 +20,7 @@
from marvin.cloudstackTestCase import cloudstackTestCase
from marvin.lib.utils import (random_gen,
cleanup_resources)
+from marvin.cloudstackAPI import *
from marvin.lib.base import (Domain,
Account,
ServiceOffering,
@@ -43,6 +44,8 @@
from marvin.cloudstackException import CloudstackAPIException
import time
+from pyVmomi.VmomiSupport import GetVersionFromVersionUri
+
class Services:
@@ -96,7 +99,7 @@ def __init__(self):
"template": {
"displaytext": "Public Template",
"name": "Public template",
- "ostype": 'CentOS 5.3 (64-bit)',
+ "ostype": 'CentOS 5.6 (64-bit)',
"url": "",
"hypervisor": '',
"format": '',
@@ -110,8 +113,7 @@ def __init__(self):
"privateport": 22,
"protocol": 'TCP',
},
- "ostype": 'CentOS 5.3 (64-bit)',
- # Cent OS 5.3 (64 bit)
+ "ostype": 'CentOS 5.6 (64-bit)',
"sleep": 60,
"timeout": 10,
}
@@ -249,6 +251,11 @@ def test_01_create_account(self):
user_response.state,
"Check state of created user"
)
+ self.assertEqual(
+ "native",
+ user_response.usersource,
+ "Check user source of created user"
+ )
return
@@ -1649,6 +1656,7 @@ def test_user_key_renew_same_account(self):
user.apikey,
userkeys.apikey,
"Check User api key")
+ user.secretkey = self.get_secret_key(user.id)
self.assertEqual(
user.secretkey,
userkeys.secretkey,
@@ -1664,11 +1672,18 @@ def test_user_key_renew_same_account(self):
userkeys.apikey,
new_keys.apikey,
"Check API key is different")
+ new_keys.secretkey = self.get_secret_key(user_1.id)
self.assertNotEqual(
userkeys.secretkey,
new_keys.secretkey,
"Check secret key is different")
+ def get_secret_key(self, id):
+ cmd = getUserKeys.getUserKeysCmd()
+ cmd.id = id
+ keypair = self.apiclient.getUserKeys(cmd)
+ return keypair.secretkey
+
@attr(tags=[
"role",
"accounts",
@@ -2066,3 +2081,4 @@ def test_DeleteDomain(self):
with self.assertRaises(Exception):
domain.delete(self.apiclient, cleanup=False)
return
+
diff --git a/test/integration/component/test_escalations_vmware.py b/test/integration/component/test_escalations_vmware.py
index 11696251268..098ece07af4 100644
--- a/test/integration/component/test_escalations_vmware.py
+++ b/test/integration/component/test_escalations_vmware.py
@@ -25,6 +25,7 @@
ServiceOffering,
Volume,
DiskOffering,
+ VmSnapshot,
Template,
listConfigurations)
from marvin.lib.common import (get_domain,list_isos,
@@ -44,6 +45,7 @@ def setUpClass(cls):
cls.testClient = super(TestVMware, cls).getClsTestClient()
cls.api_client = cls.testClient.getApiClient()
cls.services = cls.testClient.getParsedTestDataConfig()
+ cls.hypervisor = cls.testClient.getHypervisorInfo()
# Get Domain, Zone, Template
cls.domain = get_domain(cls.api_client)
cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests())
@@ -331,3 +333,38 @@ def test3_attach_ISO_in_RHEL7OSVM(self):
self.assertEqual(attachedIsoName, "vmware-tools.iso", "vmware-tools.iso not attached")
return
+ @attr(tags=["advanced", "basic"], required_hardware="true")
+ def test_04_check_vm_snapshot_creation_after_Instance_creation(self):
+ """
+ @summary: Test if Snapshot creation is successful
+ after VM deployment
+ CLOUDSTACK-8830 : VM snapshot creation fails for 12 min
+
+ Step1: Create a VM with any Service offering
+ Step2: Create a VM snapshot
+ Step3: Verify is VM SS creation is failed
+ """
+
+ if self.hypervisor.lower() not in ['vmware']:
+ self.skipTest("This test case is only for vmware. Hence, skipping the test")
+ vm = VirtualMachine.create(
+ self.userapiclient,
+ self.services["virtual_machine"],
+ accountid=self.account.name,
+ domainid=self.account.domainid,
+ serviceofferingid=self.service_offering.id,
+ templateid=self.template.id,
+ zoneid=self.zone.id
+ )
+
+ snapshot_created_1 = VmSnapshot.create(
+ self.userapiclient,
+ vm.id
+ )
+ self.assertIsNotNone(
+ snapshot_created_1,
+ "VM Snapshot creation failed"
+ )
+
+
+
diff --git a/test/integration/component/test_host.py b/test/integration/component/test_host.py
new file mode 100644
index 00000000000..6a46d2ab035
--- /dev/null
+++ b/test/integration/component/test_host.py
@@ -0,0 +1,205 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __builtin__ import False
+""" BVT tests for Hosts Test
+"""
+
+# Import Local Modules
+from marvin.codes import FAILED
+from marvin.cloudstackTestCase import *
+from marvin.cloudstackAPI import *
+from marvin.lib.utils import *
+from marvin.lib.base import *
+from marvin.lib.common import *
+from nose.plugins.attrib import attr
+from marvin.sshClient import SshClient
+import time
+from time import sleep
+
+_multiprocess_shared_ = False
+
+
+class TestHostHA(cloudstackTestCase):
+
+ def setUp(self):
+ self.logger = logging.getLogger('TestHM')
+ self.stream_handler = logging.StreamHandler()
+ self.logger.setLevel(logging.DEBUG)
+ self.logger.addHandler(self.stream_handler)
+ self.apiclient = self.testClient.getApiClient()
+ self.hypervisor = self.testClient.getHypervisorInfo()
+ self.mgtSvrDetails = self.config.__dict__["mgtSvr"][0].__dict__
+ self.dbclient = self.testClient.getDbConnection()
+ self.services = self.testClient.getParsedTestDataConfig()
+ self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests())
+ self.pod = get_pod(self.apiclient, self.zone.id)
+ self.cleanup = []
+ self.services = {
+ "service_offering": {
+ "name": "Ultra Tiny Instance",
+ "displaytext": "Ultra Tiny Instance",
+ "cpunumber": 1,
+ "cpuspeed": 100,
+ "memory": 128,
+ },
+ "service_offering_local": {
+ "name": "Ultra Tiny Local Instance",
+ "displaytext": "Ultra Tiny Local Instance",
+ "cpunumber": 1,
+ "cpuspeed": 100,
+ "memory": 128,
+ "storagetype": "local"
+ },
+ "vm": {
+ "username": "root",
+ "password": "password",
+ "ssh_port": 22,
+ # Hypervisor type should be same as
+ # hypervisor type of cluster
+ "privateport": 22,
+ "publicport": 22,
+ "protocol": 'TCP',
+ },
+ "natrule": {
+ "privateport": 22,
+ "publicport": 22,
+ "startport": 22,
+ "endport": 22,
+ "protocol": "TCP",
+ "cidrlist": '0.0.0.0/0',
+ },
+ "ostype": 'CentOS 5.3 (64-bit)',
+ "sleep": 60,
+ "timeout": 10,
+ }
+
+
+ def tearDown(self):
+ try:
+ # Clean up, terminate the created templates
+ cleanup_resources(self.apiclient, self.cleanup)
+
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+
+ return
+
+
+
+
+ def checkHostDown(self, fromHostIp, testHostIp):
+ try:
+ ssh = SshClient(fromHostIp, 22, "root", "password")
+ res = ssh.execute("ping -c 1 %s" % testHostIp)
+ result = str(res)
+ if result.count("100% packet loss") == 1:
+ return True, 1
+ else:
+ return False, 1
+ except Exception as e:
+ self.logger.debug("Got exception %s" % e)
+ return False, 1
+
+ def checkHostUp(self, fromHostIp, testHostIp):
+ try:
+ ssh = SshClient(fromHostIp, 22, "root", "password")
+ res = ssh.execute("ping -c 1 %s" % testHostIp)
+ result = str(res)
+ if result.count(" 0% packet loss") == 1:
+ return True, 1
+ else:
+ return False, 1
+ except Exception as e:
+ self.logger.debug("Got exception %s" % e)
+ return False, 1
+
+ def checkHostStateInCloudstack(self, state, hostId):
+ try:
+ listHost = Host.list(
+ self.apiclient,
+ type='Routing',
+ zoneid=self.zone.id,
+ podid=self.pod.id,
+ id=hostId
+ )
+ self.assertEqual(
+ isinstance(listHost, list),
+ True,
+ "Check if listHost returns a valid response"
+ )
+
+ self.assertEqual(
+ len(listHost),
+ 1,
+ "Check if listHost returns a host"
+ )
+ self.logger.debug(" Host state is %s " % listHost[0].state)
+ if listHost[0].state == state:
+ return True, 1
+ else:
+ return False, 1
+ except Exception as e:
+ self.logger.debug("Got exception %s" % e)
+ return False, 1
+
+ def updateConfigurAndRestart(self, name, value):
+ Configurations.update(self.apiclient, name, value)
+ self.RestartServers()
+ time.sleep(self.services["sleep"])
+
+ def RestartServers(self):
+ """ Restart management
+ server and usage server """
+ sshClient = SshClient(self.mgtSvrDetails["mgtSvrIp"],
+ 22,
+ self.mgtSvrDetails["user"],
+ self.mgtSvrDetails["passwd"]
+ )
+ command = "service cloudstack-management restart"
+ sshClient.execute(command)
+ return
+
+ @attr(
+ tags=[
+ "advanced",
+ "advancedns",
+ "smoke",
+ "basic",
+ "eip",
+ "sg"],
+ required_hardware="true")
+ def test_01_host_ha_with_nfs_storagepool_with_vm(self):
+ Configurations.update(self.apiclient, "ping.timeout", "150")
+ self.updateConfigurAndRestart("ping.interval", "150")
+
+ listHost = Host.list(
+ self.apiclient,
+ type='Routing',
+ zoneid=self.zone.id,
+ podid=self.pod.id,
+ )
+ for host in listHost:
+ self.logger.debug('Hypervisor = {}'.format(host.id))
+
+
+ hostToTest = listHost[0]
+ hostUpInCloudstack = wait_until(10, 10, self.checkHostUp, hostToTest.ipaddress, hostToTest.ipaddress)
+ #hostUpInCloudstack = wait_until(40, 10, self.checkHostStateInCloudstack, "Up", hostToTest.id)
+
+ if not(hostUpInCloudstack):
+ raise self.fail("Host is not up %s, in cloudstack so failing test " % (hostToTest.ipaddress))
+ return
diff --git a/test/integration/component/test_host_ha.py b/test/integration/component/test_host_ha.py
index 6361564e816..2af5ea93eb7 100644
--- a/test/integration/component/test_host_ha.py
+++ b/test/integration/component/test_host_ha.py
@@ -84,7 +84,7 @@ def setUp(self):
"sleep": 60,
"timeout": 10,
}
-
+
def tearDown(self):
try:
@@ -95,20 +95,20 @@ def tearDown(self):
raise Exception("Warning: Exception during cleanup : %s" % e)
return
-
+
+
def createVMs(self, hostId, number, local):
-
self.template = get_template(
self.apiclient,
self.zone.id,
self.services["ostype"]
)
-
+
if self.template == FAILED:
assert False, "get_template() failed to return template with description %s" % self.services["ostype"]
-
+
self.logger.debug("Using template %s " % self.template.id)
-
+
if local:
self.service_offering = ServiceOffering.create(
self.apiclient,
@@ -119,10 +119,9 @@ def createVMs(self, hostId, number, local):
self.apiclient,
self.services["service_offering"]
)
-
-
+
self.logger.debug("Using service offering %s " % self.service_offering.id)
-
+
vms = []
for i in range(0, number):
self.services["vm"]["zoneid"] = self.zone.id
@@ -139,7 +138,7 @@ def createVMs(self, hostId, number, local):
self.cleanup.append(vm)
self.logger.debug("VM create = {}".format(vm.id))
return vm
-
+
def noOfVMsOnHost(self, hostId):
listVms = VirtualMachine.list(
self.apiclient,
@@ -150,12 +149,12 @@ def noOfVMsOnHost(self, hostId):
for vm in listVms:
self.logger.debug('VirtualMachine on Hyp 1 = {}'.format(vm.id))
vmnos = vmnos + 1
-
+
return vmnos
-
+
def checkHostDown(self, fromHostIp, testHostIp):
try:
- ssh = SshClient(fromHostIp, 22, "root", "password")
+ ssh = SshClient(fromHostIp, 22, "root", "password")
res = ssh.execute("ping -c 1 %s" % testHostIp)
result = str(res)
if result.count("100% packet loss") == 1:
@@ -165,10 +164,10 @@ def checkHostDown(self, fromHostIp, testHostIp):
except Exception as e:
self.logger.debug("Got exception %s" % e)
return False, 1
-
+
def checkHostUp(self, fromHostIp, testHostIp):
try:
- ssh = SshClient(fromHostIp, 22, "root", "password")
+ ssh = SshClient(fromHostIp, 22, "root", "password")
res = ssh.execute("ping -c 1 %s" % testHostIp)
result = str(res)
if result.count(" 0% packet loss") == 1:
@@ -178,8 +177,8 @@ def checkHostUp(self, fromHostIp, testHostIp):
except Exception as e:
self.logger.debug("Got exception %s" % e)
return False, 1
-
-
+
+
def isOnlyNFSStorageAvailable(self):
if self.zone.localstorageenabled:
return False
@@ -196,13 +195,13 @@ def isOnlyNFSStorageAvailable(self):
for storage_pool in storage_pools:
if storage_pool.type == u'NetworkFilesystem':
return True
-
+
return False
-
+
def isOnlyLocalStorageAvailable(self):
if not(self.zone.localstorageenabled):
return False
-
+
storage_pools = StoragePool.list(
self.apiclient,
zoneid=self.zone.id,
@@ -216,13 +215,13 @@ def isOnlyLocalStorageAvailable(self):
for storage_pool in storage_pools:
if storage_pool.type == u'NetworkFilesystem':
return False
-
+
return True
-
+
def isLocalAndNFSStorageAvailable(self):
if not(self.zone.localstorageenabled):
return False
-
+
storage_pools = StoragePool.list(
self.apiclient,
zoneid=self.zone.id,
@@ -236,10 +235,10 @@ def isLocalAndNFSStorageAvailable(self):
for storage_pool in storage_pools:
if storage_pool.type == u'NetworkFilesystem':
return True
-
+
return False
-
-
+
+
def checkHostStateInCloudstack(self, state, hostId):
try:
listHost = Host.list(
@@ -254,7 +253,7 @@ def checkHostStateInCloudstack(self, state, hostId):
True,
"Check if listHost returns a valid response"
)
-
+
self.assertEqual(
len(listHost),
1,
@@ -268,19 +267,30 @@ def checkHostStateInCloudstack(self, state, hostId):
except Exception as e:
self.logger.debug("Got exception %s" % e)
return False, 1
-
-
+
+
def disconnectHostfromNetwork(self, hostIp, timeout):
srcFile = os.path.dirname(os.path.realpath(__file__)) + "/test_host_ha.sh"
if not(os.path.isfile(srcFile)):
self.logger.debug("File %s not found" % srcFile)
raise unittest.SkipTest("Script file %s required for HA not found" % srcFile);
-
+
+ ssh = SshClient(hostIp, 22, "root", "password")
+ ssh.scp(srcFile, "/root/test_host_ha.sh")
+ ssh.execute("nohup sh /root/test_host_ha.sh -t %s -d all > /dev/null 2>&1 &\n" % timeout)
+ return
+
+ def stopAgentOnHost(self, hostIp, timeout):
+ srcFile = os.path.dirname(os.path.realpath(__file__)) + "/test_host_ha.sh"
+ if not(os.path.isfile(srcFile)):
+ self.logger.debug("File %s not found" % srcFile)
+ raise unittest.SkipTest("Script file %s required for HA not found" % srcFile);
+
ssh = SshClient(hostIp, 22, "root", "password")
ssh.scp(srcFile, "/root/test_host_ha.sh")
- ssh.execute("nohup sh /root/test_host_ha.sh %s > /dev/null 2>&1 &\n" % timeout)
+ ssh.execute("nohup sh /root/test_host_ha.sh -t %s -d agent > /dev/null 2>&1 &\n" % timeout)
return
-
+
@attr(
tags=[
@@ -292,11 +302,13 @@ def disconnectHostfromNetwork(self, hostIp, timeout):
"sg"],
required_hardware="true")
def test_01_host_ha_with_nfs_storagepool_with_vm(self):
-
+ raise unittest.SkipTest("Skipping this test as this is for NFS store only.");
+ return
+
if not(self.isOnlyNFSStorageAvailable()):
raise unittest.SkipTest("Skipping this test as this is for NFS store only.");
return
-
+
listHost = Host.list(
self.apiclient,
type='Routing',
@@ -305,61 +317,61 @@ def test_01_host_ha_with_nfs_storagepool_with_vm(self):
)
for host in listHost:
self.logger.debug('Hypervisor = {}'.format(host.id))
-
-
+
+
if len(listHost) != 2:
self.logger.debug("Host HA can be tested with two host only %s, found" % len(listHost));
raise unittest.SkipTest("Host HA can be tested with two host only %s, found" % len(listHost));
return
-
+
no_of_vms = self.noOfVMsOnHost(listHost[0].id)
-
+
no_of_vms = no_of_vms + self.noOfVMsOnHost(listHost[1].id)
-
+
self.logger.debug("Number of VMS on hosts = %s" % no_of_vms)
-
-
+
+
if no_of_vms < 5:
self.logger.debug("test_01: Create VMs as there are not enough vms to check host ha")
no_vm_req = 5 - no_of_vms
if (no_vm_req > 0):
self.logger.debug("Creating vms = {}".format(no_vm_req))
self.vmlist = self.createVMs(listHost[0].id, no_vm_req, False)
-
+
ha_host = listHost[1]
other_host = listHost[0]
if self.noOfVMsOnHost(listHost[0].id) > self.noOfVMsOnHost(listHost[1].id):
ha_host = listHost[0]
other_host = listHost[1]
-
+
self.disconnectHostfromNetwork(ha_host.ipaddress, 400)
-
+
hostDown = wait_until(10, 10, self.checkHostDown, other_host.ipaddress, ha_host.ipaddress)
- if not(hostDown):
+ if not(hostDown):
raise unittest.SkipTest("Host %s is not down, cannot proceed with test" % (ha_host.ipaddress))
-
+
hostDownInCloudstack = wait_until(40, 10, self.checkHostStateInCloudstack, "Down", ha_host.id)
#the test could have failed here but we will try our best to get host back in consistent state
-
+
no_of_vms = self.noOfVMsOnHost(ha_host.id)
no_of_vms = no_of_vms + self.noOfVMsOnHost(other_host.id)
self.logger.debug("Number of VMS on hosts = %s" % no_of_vms)
#
hostUp = wait_until(10, 10, self.checkHostUp, other_host.ipaddress, ha_host.ipaddress)
- if not(hostUp):
+ if not(hostUp):
self.logger.debug("Host is down %s, though HA went fine, the environment is not consistent " % (ha_host.ipaddress))
-
-
+
+
hostUpInCloudstack = wait_until(40, 10, self.checkHostStateInCloudstack, "Up", ha_host.id)
-
- if not(hostDownInCloudstack):
+
+ if not(hostDownInCloudstack):
raise self.fail("Host is not down %s, in cloudstack so failing test " % (ha_host.ipaddress))
- if not(hostUpInCloudstack):
+ if not(hostUpInCloudstack):
raise self.fail("Host is not up %s, in cloudstack so failing test " % (ha_host.ipaddress))
-
+
return
-
+
@attr(
tags=[
"advanced",
@@ -370,11 +382,12 @@ def test_01_host_ha_with_nfs_storagepool_with_vm(self):
"sg"],
required_hardware="true")
def test_02_host_ha_with_local_storage_and_nfs(self):
-
+ raise unittest.SkipTest("Skipping this test as this is for NFS store only.");
+ return
if not(self.isLocalAndNFSStorageAvailable()):
raise unittest.SkipTest("Skipping this test as this is for Local storage and NFS storage only.");
return
-
+
listHost = Host.list(
self.apiclient,
type='Routing',
@@ -383,62 +396,62 @@ def test_02_host_ha_with_local_storage_and_nfs(self):
)
for host in listHost:
self.logger.debug('Hypervisor = {}'.format(host.id))
-
-
+
+
if len(listHost) != 2:
self.logger.debug("Host HA can be tested with two host only %s, found" % len(listHost));
raise unittest.SkipTest("Host HA can be tested with two host only %s, found" % len(listHost));
return
-
+
no_of_vms = self.noOfVMsOnHost(listHost[0].id)
-
+
no_of_vms = no_of_vms + self.noOfVMsOnHost(listHost[1].id)
-
+
self.logger.debug("Number of VMS on hosts = %s" % no_of_vms)
-
-
+
+
if no_of_vms < 5:
self.logger.debug("test_02: Create VMs as there are not enough vms to check host ha")
no_vm_req = 5 - no_of_vms
if (no_vm_req > 0):
self.logger.debug("Creating vms = {}".format(no_vm_req))
self.vmlist = self.createVMs(listHost[0].id, no_vm_req, True)
-
+
ha_host = listHost[1]
other_host = listHost[0]
if self.noOfVMsOnHost(listHost[0].id) > self.noOfVMsOnHost(listHost[1].id):
ha_host = listHost[0]
other_host = listHost[1]
-
+
self.disconnectHostfromNetwork(ha_host.ipaddress, 400)
-
+
hostDown = wait_until(10, 10, self.checkHostDown, other_host.ipaddress, ha_host.ipaddress)
- if not(hostDown):
+ if not(hostDown):
raise unittest.SkipTest("Host %s is not down, cannot proceed with test" % (ha_host.ipaddress))
-
+
hostDownInCloudstack = wait_until(40, 10, self.checkHostStateInCloudstack, "Down", ha_host.id)
#the test could have failed here but we will try our best to get host back in consistent state
-
+
no_of_vms = self.noOfVMsOnHost(ha_host.id)
no_of_vms = no_of_vms + self.noOfVMsOnHost(other_host.id)
self.logger.debug("Number of VMS on hosts = %s" % no_of_vms)
#
hostUp = wait_until(10, 10, self.checkHostUp, other_host.ipaddress, ha_host.ipaddress)
- if not(hostUp):
+ if not(hostUp):
self.logger.debug("Host is down %s, though HA went fine, the environment is not consistent " % (ha_host.ipaddress))
-
-
+
+
hostUpInCloudstack = wait_until(40, 10, self.checkHostStateInCloudstack, "Up", ha_host.id)
-
- if not(hostDownInCloudstack):
+
+ if not(hostDownInCloudstack):
raise self.fail("Host is not down %s, in cloudstack so failing test " % (ha_host.ipaddress))
- if not(hostUpInCloudstack):
+ if not(hostUpInCloudstack):
raise self.fail("Host is not up %s, in cloudstack so failing test " % (ha_host.ipaddress))
-
+
return
-
-
-
+
+
+
@attr(
tags=[
"advanced",
@@ -449,11 +462,13 @@ def test_02_host_ha_with_local_storage_and_nfs(self):
"sg"],
required_hardware="true")
def test_03_host_ha_with_only_local_storage(self):
-
+ raise unittest.SkipTest("Skipping this test as this is for NFS store only.");
+ return
+
if not(self.isOnlyLocalStorageAvailable()):
raise unittest.SkipTest("Skipping this test as this is for Local storage only.");
return
-
+
listHost = Host.list(
self.apiclient,
type='Routing',
@@ -462,55 +477,125 @@ def test_03_host_ha_with_only_local_storage(self):
)
for host in listHost:
self.logger.debug('Hypervisor = {}'.format(host.id))
-
-
+
+
if len(listHost) != 2:
self.logger.debug("Host HA can be tested with two host only %s, found" % len(listHost));
raise unittest.SkipTest("Host HA can be tested with two host only %s, found" % len(listHost));
return
-
+
no_of_vms = self.noOfVMsOnHost(listHost[0].id)
-
+
no_of_vms = no_of_vms + self.noOfVMsOnHost(listHost[1].id)
-
+
self.logger.debug("Number of VMS on hosts = %s" % no_of_vms)
-
+
if no_of_vms < 5:
self.logger.debug("test_03: Create VMs as there are not enough vms to check host ha")
no_vm_req = 5 - no_of_vms
if (no_vm_req > 0):
self.logger.debug("Creating vms = {}".format(no_vm_req))
self.vmlist = self.createVMs(listHost[0].id, no_vm_req, True)
-
+
ha_host = listHost[1]
other_host = listHost[0]
if self.noOfVMsOnHost(listHost[0].id) > self.noOfVMsOnHost(listHost[1].id):
ha_host = listHost[0]
other_host = listHost[1]
-
+
self.disconnectHostfromNetwork(ha_host.ipaddress, 400)
-
+
hostDown = wait_until(10, 10, self.checkHostDown, other_host.ipaddress, ha_host.ipaddress)
- if not(hostDown):
+ if not(hostDown):
raise unittest.SkipTest("Host %s is not down, cannot proceed with test" % (ha_host.ipaddress))
-
+
hostDownInCloudstack = wait_until(40, 10, self.checkHostStateInCloudstack, "Alert", ha_host.id)
#the test could have failed here but we will try our best to get host back in consistent state
-
+
no_of_vms = self.noOfVMsOnHost(ha_host.id)
no_of_vms = no_of_vms + self.noOfVMsOnHost(other_host.id)
self.logger.debug("Number of VMS on hosts = %s" % no_of_vms)
#
hostUp = wait_until(10, 10, self.checkHostUp, other_host.ipaddress, ha_host.ipaddress)
- if not(hostUp):
+ if not(hostUp):
self.logger.debug("Host is down %s, though HA went fine, the environment is not consistent " % (ha_host.ipaddress))
-
-
+
+
hostUpInCloudstack = wait_until(40, 10, self.checkHostStateInCloudstack, "Up", ha_host.id)
-
- if not(hostDownInCloudstack):
+
+ if not(hostDownInCloudstack):
raise self.fail("Host is not in alert %s, in cloudstack so failing test " % (ha_host.ipaddress))
- if not(hostUpInCloudstack):
+ if not(hostUpInCloudstack):
+ raise self.fail("Host is not up %s, in cloudstack so failing test " % (ha_host.ipaddress))
+
+ return
+
+
+ @attr(
+ tags=[
+ "advanced",
+ "advancedns",
+ "smoke",
+ "basic",
+ "eip",
+ "sg"],
+ required_hardware="true")
+ def test_04_host_ha_vmactivity_check(self):
+
+ if not(self.isOnlyNFSStorageAvailable()):
+ raise unittest.SkipTest("Skipping this test as this is for NFS store only.");
+ return
+
+ listHost = Host.list(
+ self.apiclient,
+ type='Routing',
+ zoneid=self.zone.id,
+ podid=self.pod.id,
+ )
+ for host in listHost:
+ self.logger.debug('Hypervisor = {}'.format(host.id))
+
+
+ if len(listHost) != 2:
+ self.logger.debug("Host HA can be tested with two host only %s, found" % len(listHost));
+ raise unittest.SkipTest("Host HA can be tested with two host only %s, found" % len(listHost));
+ return
+
+ no_of_vms = self.noOfVMsOnHost(listHost[0].id)
+
+ no_of_vms = no_of_vms + self.noOfVMsOnHost(listHost[1].id)
+
+ self.logger.debug("Number of VMS on hosts = %s" % no_of_vms)
+
+
+ if no_of_vms < 5:
+ self.logger.debug("test_01: Create VMs as there are not enough vms to check host ha")
+ no_vm_req = 5 - no_of_vms
+ if (no_vm_req > 0):
+ self.logger.debug("Creating vms = {}".format(no_vm_req))
+ self.vmlist = self.createVMs(listHost[0].id, no_vm_req, False)
+
+ ha_host = listHost[1]
+ other_host = listHost[0]
+ if self.noOfVMsOnHost(listHost[0].id) > self.noOfVMsOnHost(listHost[1].id):
+ ha_host = listHost[0]
+ other_host = listHost[1]
+
+ self.stopAgentOnHost(ha_host.ipaddress, 150)
+
+ hostDisconnectedInCloudstack = wait_until(40, 10, self.checkHostStateInCloudstack, "Disconnected", ha_host.id)
+ #the test could have failed here but we will try our best to get host back in consistent state
+
+ no_of_vms = self.noOfVMsOnHost(ha_host.id)
+ no_of_vms = no_of_vms + self.noOfVMsOnHost(other_host.id)
+ self.logger.debug("Number of VMS on hosts = %s" % no_of_vms)
+ #
+
+ hostUpInCloudstack = wait_until(40, 10, self.checkHostStateInCloudstack, "Up", ha_host.id)
+
+ if not(hostDisconnectedInCloudstack):
+ raise self.fail("Host is not disconnected %s, in cloudstack so failing test " % (ha_host.ipaddress))
+ if not(hostUpInCloudstack):
raise self.fail("Host is not up %s, in cloudstack so failing test " % (ha_host.ipaddress))
-
- return
\ No newline at end of file
+
+ return
diff --git a/test/integration/component/test_host_ha.sh b/test/integration/component/test_host_ha.sh
index 85aadb1b688..b27038840c9 100755
--- a/test/integration/component/test_host_ha.sh
+++ b/test/integration/component/test_host_ha.sh
@@ -1,40 +1,100 @@
#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
-#bring down all eth interfaces
+set -x
-usage() { echo "Usage: $0 <duration in seconds for downing all network interfaces>"; exit 1; }
+usage() { echo "Usage: $0 -d <all|agent> -t <duration in seconds for downing all network interfaces>"; exit 1; }
-case $1 in
+Interval=
+Down=
+while getopts 'd:t:' OPTION
+do
+ case $OPTION in
+ d)
+ Down="$OPTARG"
+ ;;
+ t)
+ Interval="$OPTARG"
+ ;;
+ *)
+ usage
+ ;;
+ esac
+done
+
+
+if [ -z $Interval ]; then
+ usage
+fi
+
+
+if [ "$Down" != 'all' ]; then
+ if [ "$Down" != 'agent' ]; then
+ usage
+ fi
+fi
+
+case $Interval in
''|*[!0-9]*) echo "The parameter should be an integer"; exit ;;
*) echo $1 ;;
esac
-if [ -z $1 ]; then
- usage
-elif [ $1 -lt 1 ]; then
+if [ $Interval -lt 1 ]; then
echo "Down time should be at least 1 second"
exit 1
-elif [ $1 -gt 5000 ]; then
+elif [ $Interval -gt 5000 ]; then
echo "Down time should be less than 5000 second"
exit 1
fi
-for i in `ifconfig -a | sed 's/[ \t].*//;/^\(lo\|\)$/d' | grep eth`
+
+for i in `ifconfig -a | sed 's/[ \t].*//;/^\(lo\|\)$/d' | grep "^eth.$"`
do
- ifconfig $i down
+ ifconfig $i down
done
service cloudstack-agent stop
update-rc.d -f cloudstack-agent remove
-sleep $1
+sleep 1
-for i in `ifconfig -a | sed 's/[ \t].*//;/^\(lo\|\)$/d' | grep eth`
+if [ "$Down" = 'agent' ]; then
+ for i in `ifconfig -a | sed 's/[ \t].*//;/^\(lo\|\)$/d' | grep "^eth.$"`
+ do
+ ifconfig $i up
+ done
+fi
+
+counter=$Interval
+while [ $counter -gt 0 ]
do
- ifconfig $i up
+ sleep 1
+ counter=$(( $counter - 1 ))
done
+if [ "$Down" = 'all' ]; then
+ for i in `ifconfig -a | sed 's/[ \t].*//;/^\(lo\|\)$/d' | grep eth`
+ do
+ ifconfig $i up
+ done
+fi
+
update-rc.d -f cloudstack-agent defaults
-service cloudstack-agent start
\ No newline at end of file
+service cloudstack-agent start
diff --git a/test/integration/component/test_ncc_integration_dedicated.py b/test/integration/component/test_ncc_integration_dedicated.py
new file mode 100755
index 00000000000..b02d0513779
--- /dev/null
+++ b/test/integration/component/test_ncc_integration_dedicated.py
@@ -0,0 +1,269 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""
+BVT tests for NCC integration with cloudstack
+"""
+#Import Local Modules
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.common import get_domain, get_zone, get_template
+from marvin.lib import ncc
+from marvin.lib.base import (Account,
+ VirtualMachine,
+ PublicIPAddress,
+ LoadBalancerRule,
+ ServiceOffering,
+ NetworkOffering,
+ Network,
+ NATRule,
+ PhysicalNetwork,
+ NetworkServiceProvider,
+ RegisteredServicePackage)
+from marvin.lib.utils import cleanup_resources
+from nose.plugins.attrib import attr
+import logging
+
+
+class TestNccIntegrationDedicated(cloudstackTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.testClient = super(TestNccIntegrationDedicated, cls).getClsTestClient()
+ cls.api_client = cls.testClient.getApiClient()
+ cls.services = cls.testClient.getParsedTestDataConfig()
+ cls._cleanup = []
+
+ cls.logger = logging.getLogger('TestNccIntegrationDedicated')
+ cls.stream_handler = logging.StreamHandler()
+ cls.logger.setLevel(logging.DEBUG)
+ cls.logger.addHandler(cls.stream_handler)
+
+ # Get Zone, Domain and templates
+ cls.domain = get_domain(cls.api_client)
+ cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests())
+ cls.services['mode'] = cls.zone.networktype
+ cls.template = get_template(
+ cls.api_client,
+ cls.zone.id,
+ cls.services["ostype"] )
+ ncc_ip = cls.services["NCC"]["NCCIP"]
+ ns_ip = cls.services["NSDedicated"]["NSIP"]
+ cls.debug("NS IP - Dedicated: %s" % ns_ip)
+
+ mgmt_srv_ip = cls.config.__dict__["mgtSvr"][0].__dict__["mgtSvrIp"]
+ #ncc_ip = "10.102.195.215"
+ #ns_ip = "10.102.195.210"
+ cls.ns = ncc.NCC(ncc_ip, ns_ip, mgmt_srv_ip, logger=cls.logger)
+ cls.ns.registerCCP(cls.api_client)
+ cls.ns.registerNS()
+ cls.ns.assignNStoCSZone()
+ spname = cls.services["servicepackage_dedicated"]["name"]
+
+ # Create Service package and get device group id, tenant group id and service package id
+ # These would be needed later for clean up
+
+ (cls.dv_group_id, cls.tnt_group_id, cls.srv_pkg_id) = cls.ns.createServicePackages(
+ spname,
+ "NetScalerVPX",
+ ns_ip,
+ isolation_policy="dedicated")
+ cls.debug("Created service package in NCC")
+ cls.debug("dv_group, tnt_group, srv_pkg_id: %s %s %s" %(cls.dv_group_id,cls.tnt_group_id, cls.srv_pkg_id))
+
+ srv_pkg_list = RegisteredServicePackage.list(cls.api_client)
+ # Choose the one created
+ cls.srv_pkg_uuid = None
+ for sp in srv_pkg_list:
+ if sp.name == spname:
+ cls.srv_pkg_uuid = sp.id
+ #srv_pkg_id = srv_pkg_list[0].id
+
+ cls.account = Account.create(
+ cls.api_client,
+ cls.services["account"]
+ )
+ cls._cleanup.append(cls.account)
+
+ try:
+ cls.services["nw_off_ncc_DedicatedSP"]["servicepackageuuid"] = cls.srv_pkg_uuid
+ cls.services["nw_off_ncc_DedicatedSP"]["servicepackagedescription"] = "A NetScalerVPX is dedicated per network."
+ cls.network_offering = NetworkOffering.create(
+ cls.api_client,
+ cls.services["nw_off_ncc_DedicatedSP"])
+ except Exception as e:
+ raise Exception ("Unable to create network offering with Service package % s due to exception % s"
+ % (cls.srv_pkg_uuid, e))
+
+ # Network offering should be removed so that service package may be deleted later
+ cls._cleanup.append(cls.network_offering)
+
+ cls.network_offering.update(cls.api_client, state = "Enabled")
+ cls.service_offering = ServiceOffering.create(
+ cls.api_client,
+ cls.services["service_offering"]
+ )
+ cls.services["small"]["template"] = cls.template.id
+
+ # Enable Netscaler Service Provider
+
+ cls.phy_nws = PhysicalNetwork.list(cls.api_client,zoneid=cls.zone.id)
+ if isinstance(cls.phy_nws, list):
+ physical_network = cls.phy_nws[0]
+
+ try:
+ cls.ns_service_provider = NetworkServiceProvider.list(cls.api_client,name='Netscaler')
+ if isinstance(cls.ns_service_provider, list):
+ ns_provider = cls.ns_service_provider[0]
+ except:
+ raise Exception ("Netscaler service provider not found!!")
+
+ try:
+ if ns_provider.state != "Enabled":
+ NetworkServiceProvider.update(cls.api_client, id=ns_provider.id, physicalnetworkid=physical_network.id, state="Enabled")
+ except:
+ raise Exception ("Enabling Netscaler Service provider failed. Unable to proceed")
+
+ return
+
+ @classmethod
+ def tearDownClass(cls):
+ try:
+ # Cleanup resources used
+ cleanup_resources(cls.api_client, cls._cleanup)
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+ cls.ns.cleanup_ncc(cls.dv_group_id, cls.srv_pkg_uuid, cls.srv_pkg_id, cls.tnt_group_id)
+ return
+
+ def setUp(self):
+ self.apiclient = self.testClient.getApiClient()
+ return
+
+ def tearDown(self):
+ return
+
+
+ @attr(tags=["ncc"], required_hardware="true")
+ def test_01_dedicated_first_network(self):
+ # Create network
+ self.debug("Creating network with network offering: %s" % self.network_offering.id)
+ self.network = Network.create(
+ self.apiclient,
+ self.services["network"],
+ accountid=self.account.name,
+ domainid=self.account.domainid,
+ networkofferingid=self.network_offering.id,
+ zoneid=self.zone.id
+ )
+ self.debug("Created network: %s" % self.network.id)
+
+ self.debug("Trying VM deploy with network created on account: %s" % self.account.name)
+
+ self.virtual_machine = VirtualMachine.create(
+ self.apiclient,
+ self.services["small"],
+ accountid=self.account.name,
+ domainid=self.account.domainid,
+ zoneid=self.zone.id,
+ networkids=self.network.id,
+ serviceofferingid=self.service_offering.id
+ )
+ self.debug("Deployed VM in network: %s" % self.network.id)
+ list_vm_response = VirtualMachine.list(
+ self.apiclient,
+ id=self.virtual_machine.id
+ )
+ self.debug(
+ "Verify listVirtualMachines response for virtual machine: %s"
+ % self.virtual_machine.id
+ )
+
+ self.assertEqual(
+ isinstance(list_vm_response, list),
+ True,
+ "Check list response returns a valid list")
+ vm_response = list_vm_response[0]
+
+ self.assertEqual(
+ vm_response.state,
+ "Running",
+ "VM state should be running after deployment"
+ )
+
+ self.debug("Aquiring public IP for network: %s" % self.network.id)
+
+ ip_with_lb_rule = PublicIPAddress.create(
+ self.apiclient,
+ accountid=self.account.name,
+ zoneid=self.zone.id,
+ domainid=self.account.domainid,
+ networkid=self.network.id)
+
+ self.debug(
+ "Creating LB rule for IP address: %s with round robin algo" %
+ ip_with_lb_rule.ipaddress.ipaddress)
+
+ self.services["lbrule"]["alg"] = 'roundrobin'
+ lb_rule = LoadBalancerRule.create(
+ self.apiclient,
+ self.services["lbrule"],
+ ipaddressid=ip_with_lb_rule.ipaddress.id,
+ accountid=self.account.name,
+ networkid=self.network.id
+ )
+
+ lb_rules = LoadBalancerRule.list(
+ self.apiclient,
+ id=lb_rule.id,
+ listall=True
+ )
+ self.assertEqual(
+ isinstance(lb_rules, list),
+ True,
+ "List LB rules should return a newly created LB rule"
+ )
+ self.debug("Adding %s to the LB rule %s" % (
+ self.virtual_machine.name,
+ lb_rule.name
+ ))
+ lb_rule.assign(self.apiclient, [self.virtual_machine])
+
+ @attr(tags=["ncc"], required_hardware="true")
+ def test_02_dedicated_another_network(self):
+ # Create network
+ self.network = Network.create(
+ self.apiclient,
+ self.services["network"],
+ accountid=self.account.name,
+ domainid=self.account.domainid,
+ networkofferingid=self.network_offering.id,
+ zoneid=self.zone.id
+ )
+ self.debug("Created network: %s" % self.network.id)
+
+ self.debug("Trying VM deploy with network created on account: %s" % self.account.name)
+
+ with self.assertRaises(Exception):
+ self.virtual_machine = VirtualMachine.create(
+ self.apiclient,
+ self.services["small"],
+ accountid=self.account.name,
+ domainid=self.account.domainid,
+ networkids=self.network.id,
+ zoneid=self.zone.id,
+ serviceofferingid=self.service_offering.id
+ )
+ return
diff --git a/test/integration/component/test_ncc_integration_shared.py b/test/integration/component/test_ncc_integration_shared.py
new file mode 100755
index 00000000000..cb5b90ce900
--- /dev/null
+++ b/test/integration/component/test_ncc_integration_shared.py
@@ -0,0 +1,323 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""
+BVT tests for NCC integration with cloudstack
+"""
+#Import Local Modules
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.common import get_domain, get_zone, get_template
+from marvin.lib import ncc
+from marvin.lib.base import (Account,
+ VirtualMachine,
+ PublicIPAddress,
+ LoadBalancerRule,
+ ServiceOffering,
+ NetworkOffering,
+ Network,
+ NATRule,
+ PhysicalNetwork,
+ NetworkServiceProvider,
+ RegisteredServicePackage)
+from marvin.lib.utils import cleanup_resources
+from nose.plugins.attrib import attr
+import logging
+
+
+class TestNccIntegrationShared(cloudstackTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.testClient = super(TestNccIntegrationShared, cls).getClsTestClient()
+ cls.api_client = cls.testClient.getApiClient()
+ cls.services = cls.testClient.getParsedTestDataConfig()
+ cls._cleanup = []
+
+ cls.logger = logging.getLogger('TestNccIntegrationShared')
+ cls.stream_handler = logging.StreamHandler()
+ cls.logger.setLevel(logging.DEBUG)
+ cls.logger.addHandler(cls.stream_handler)
+
+ # Get Zone, Domain and templates
+ cls.domain = get_domain(cls.api_client)
+ cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests())
+ cls.services['mode'] = cls.zone.networktype
+ cls.template = get_template(
+ cls.api_client,
+ cls.zone.id,
+ cls.services["ostype"] )
+ ncc_ip=cls.services["NCC"]["NCCIP"]
+ ns_ip=cls.services["NSShared"]["NSIP"]
+ cls.debug("NS IP: Shared: %s" % ns_ip)
+
+ mgmt_srv_ip = cls.config.__dict__["mgtSvr"][0].__dict__["mgtSvrIp"]
+ #ncc_ip = "10.102.195.215"
+ #ns_ip = "10.102.195.210"
+ cls.ns = ncc.NCC(ncc_ip, ns_ip, mgmt_srv_ip, logger=cls.logger)
+ cls.ns.registerCCP(cls.api_client)
+ cls.ns.registerNS()
+ cls.ns.assignNStoCSZone()
+ spname = cls.services["servicepackage_shared"]["name"]
+ cls.debug("SPname (Shared): %s" % spname)
+ #spname="SharedSP9"
+ # Create Service package and get device group id, tenant group id and service package id
+ # These would be needed later for clean up
+
+ (cls.dv_group_id, cls.tnt_group_id, cls.srv_pkg_id) = cls.ns.createServicePackages(
+ spname,
+ "NetScalerVPX",
+ ns_ip)
+ srv_pkg_list = RegisteredServicePackage.list(cls.api_client)
+ # Choose the one created
+ cls.srv_pkg_uuid = None
+ for sp in srv_pkg_list:
+ if sp.name == spname:
+ cls.srv_pkg_uuid = sp.id
+ #srv_pkg_id = srv_pkg_list[0].id
+
+ cls.account = Account.create(
+ cls.api_client,
+ cls.services["account"]
+ )
+ cls._cleanup.append(cls.account)
+
+ try:
+ cls.services["nw_off_ncc_SharedSP"]["servicepackageuuid"] = cls.srv_pkg_uuid
+ cls.services["nw_off_ncc_SharedSP"]["servicepackagedescription"] = "A NetScalerVPX is shared across all networks."
+ cls.network_offering = NetworkOffering.create(
+ cls.api_client,
+ cls.services["nw_off_ncc_SharedSP"])
+ except Exception as e:
+ raise Exception ("Unable to create network offering with Service package % s due to exception % s"
+ % (cls.srv_pkg_uuid, e))
+
+ # Network offering should be removed so that service package may be deleted later
+ cls._cleanup.append(cls.network_offering)
+
+ cls.network_offering.update(cls.api_client, state = "Enabled")
+ cls.service_offering_shared = ServiceOffering.create(
+ cls.api_client,
+ cls.services["service_offering"]
+ )
+ cls.services["small"]["template"] = cls.template.id
+
+ # Enable Netscaler Service Provider
+
+ cls.phy_nws = PhysicalNetwork.list(cls.api_client,zoneid=cls.zone.id)
+ if isinstance(cls.phy_nws, list):
+ physical_network = cls.phy_nws[0]
+
+ try:
+ cls.ns_service_provider = NetworkServiceProvider.list(cls.api_client,name='Netscaler')
+ if isinstance(cls.ns_service_provider, list):
+ ns_provider = cls.ns_service_provider[0]
+ except:
+ raise Exception ("Netscaler service provider not found!!")
+
+ try:
+ if ns_provider.state != "Enabled":
+ NetworkServiceProvider.update(cls.api_client, id=ns_provider.id, physicalnetworkid=physical_network.id, state="Enabled")
+ except:
+ raise Exception ("Enabling Netscaler Service provider failed. Unable to proceed")
+
+ return
+
+ @classmethod
+ def tearDownClass(cls):
+ try:
+ # Cleanup resources used
+ cleanup_resources(cls.api_client, cls._cleanup)
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+ cls.ns.cleanup_ncc(cls.dv_group_id, cls.srv_pkg_uuid, cls.srv_pkg_id, cls.tnt_group_id)
+ return
+
+ def setUp(self):
+ self.apiclient = self.testClient.getApiClient()
+ return
+
+ def tearDown(self):
+ return
+
+ @attr(tags=["ncc"], required_hardware="true")
+ def test_01_shared_first_network(self):
+ # Create network
+ self.debug("Creating network with network offering: %s" % self.network_offering.id)
+ self.network = Network.create(
+ self.apiclient,
+ self.services["network"],
+ accountid=self.account.name,
+ domainid=self.account.domainid,
+ networkofferingid=self.network_offering.id,
+ zoneid=self.zone.id
+ )
+ self.debug("Created network: %s" % self.network.id)
+
+ self.debug("Trying VM deploy with network created on account: %s" % self.account.name)
+
+ self.virtual_machine = VirtualMachine.create(
+ self.apiclient,
+ self.services["small"],
+ accountid=self.account.name,
+ domainid=self.account.domainid,
+ zoneid=self.zone.id,
+ networkids=self.network.id,
+ serviceofferingid=self.service_offering_shared.id)
+ self.debug("Deployed VM in network: %s" % self.network.id)
+ list_vm_response = VirtualMachine.list(
+ self.apiclient,
+ id=self.virtual_machine.id
+ )
+ self.debug(
+ "Verify listVirtualMachines response for virtual machine: %s"
+ % self.virtual_machine.id
+ )
+
+ self.assertEqual(
+ isinstance(list_vm_response, list),
+ True,
+ "Check list response returns a valid list")
+ vm_response = list_vm_response[0]
+
+ self.assertEqual(
+ vm_response.state,
+ "Running",
+ "VM state should be running after deployment"
+ )
+
+ self.debug("Acquiring public IP for network: %s" % self.network.id)
+
+ ip_with_lb_rule = PublicIPAddress.create(
+ self.apiclient,
+ accountid=self.account.name,
+ zoneid=self.zone.id,
+ domainid=self.account.domainid,
+ networkid=self.network.id)
+
+ self.debug(
+ "Creating LB rule for IP address: %s with round robin algo" %
+ ip_with_lb_rule.ipaddress.ipaddress)
+
+ self.services["lbrule"]["alg"] = 'roundrobin'
+ lb_rule = LoadBalancerRule.create(
+ self.apiclient,
+ self.services["lbrule"],
+ ipaddressid=ip_with_lb_rule.ipaddress.id,
+ accountid=self.account.name,
+ networkid=self.network.id
+ )
+
+ lb_rules = LoadBalancerRule.list(
+ self.apiclient,
+ id=lb_rule.id,
+ listall=True
+ )
+ self.assertEqual(
+ isinstance(lb_rules, list),
+ True,
+ "List LB rules should return a newly created LB rule"
+ )
+ self.debug("Adding %s to the LB rule %s" % (
+ self.virtual_machine.name,
+ lb_rule.name
+ ))
+ lb_rule.assign(self.apiclient, [self.virtual_machine])
+
+ @attr(tags=["ncc"], required_hardware="true")
+ def test_02_shared_another_network(self):
+ # Create network
+ self.debug("Creating network with network offering: %s" % self.network_offering.id)
+ self.network = Network.create(
+ self.apiclient,
+ self.services["network"],
+ accountid=self.account.name,
+ domainid=self.account.domainid,
+ networkofferingid=self.network_offering.id,
+ zoneid=self.zone.id
+ )
+ self.debug("Created network: %s" % self.network.id)
+
+ self.debug("Trying VM deploy with network created on account: %s" % self.account.name)
+
+ self.virtual_machine = VirtualMachine.create(
+ self.apiclient,
+ self.services["small"],
+ accountid=self.account.name,
+ domainid=self.account.domainid,
+ networkids=self.network.id,
+ zoneid=self.zone.id,
+ serviceofferingid=self.service_offering_shared.id
+ )
+ self.debug("Deployed VM in network: %s" % self.network.id)
+ list_vm_response = VirtualMachine.list(
+ self.apiclient,
+ id=self.virtual_machine.id
+ )
+ self.debug(
+ "Verify listVirtualMachines response for virtual machine: %s"
+ % self.virtual_machine.id
+ )
+
+ self.assertEqual(
+ isinstance(list_vm_response, list),
+ True,
+ "Check list response returns a valid list")
+ vm_response = list_vm_response[0]
+
+ self.assertEqual(
+ vm_response.state,
+ "Running",
+ "VM state should be running after deployment"
+ )
+
+ self.debug("Aquiring public IP for network: %s" % self.network.id)
+
+ ip_with_lb_rule = PublicIPAddress.create(
+ self.apiclient,
+ accountid=self.account.name,
+ zoneid=self.zone.id,
+ domainid=self.account.domainid,
+ networkid=self.network.id)
+
+ self.debug(
+ "Creating LB rule for IP address: %s with round robin algo" %
+ ip_with_lb_rule.ipaddress.ipaddress)
+
+ self.services["lbrule"]["alg"] = 'roundrobin'
+ lb_rule = LoadBalancerRule.create(
+ self.apiclient,
+ self.services["lbrule"],
+ ipaddressid=ip_with_lb_rule.ipaddress.id,
+ accountid=self.account.name,
+ networkid=self.network.id
+ )
+
+ lb_rules = LoadBalancerRule.list(
+ self.apiclient,
+ id=lb_rule.id,
+ listall=True
+ )
+ self.assertEqual(
+ isinstance(lb_rules, list),
+ True,
+ "List LB rules should return a newly created LB rule"
+ )
+ self.debug("Adding %s to the LB rule %s" % (
+ self.virtual_machine.name,
+ lb_rule.name
+ ))
+ lb_rule.assign(self.apiclient, [self.virtual_machine])
+ return
diff --git a/test/integration/component/test_separate_backup_from_snapshot.py b/test/integration/component/test_separate_backup_from_snapshot.py
new file mode 100644
index 00000000000..c0bfe68daf6
--- /dev/null
+++ b/test/integration/component/test_separate_backup_from_snapshot.py
@@ -0,0 +1,177 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+""" P1 tests for Snapshots
+"""
+# Import Local Modules
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.config.test_data import test_data
+
+from marvin.lib.base import (Snapshot,
+ VirtualMachine,
+ Account,
+ ServiceOffering,
+ DiskOffering)
+
+from marvin.lib.common import (get_domain,
+ get_zone,
+ get_template,
+ list_volumes,
+ list_snapshots,
+ )
+
+from marvin.lib.utils import (cleanup_resources,
+ get_hypervisor_type)
+
+
+class TestSnapshots(cloudstackTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.testClient = super(TestSnapshots, cls).getClsTestClient()
+ cls.api_client = cls.testClient.getApiClient()
+
+ cls.services = test_data
+ # Get Zone, Domain and templates
+ cls.domain = get_domain(cls.api_client)
+ cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests())
+ cls._cleanup = []
+ cls.unsupportedHypervisor = False
+ cls.hypervisor = str(get_hypervisor_type(cls.api_client)).lower()
+ if cls.hypervisor.lower() in ['hyperv', 'lxc']:
+ cls.unsupportedHypervisor = True
+ return
+ cls.disk_offering = DiskOffering.create(
+ cls.api_client,
+ cls.services["disk_offering"]
+ )
+ cls.template = get_template(
+ cls.api_client,
+ cls.zone.id,
+ cls.services["ostype"]
+ )
+
+ cls.services["small"]["zoneid"] = cls.zone.id
+ cls.services["small"]["diskoffering"] = cls.disk_offering.id
+
+ cls.service_offering = ServiceOffering.create(
+ cls.api_client,
+ cls.services["service_offering"]
+ )
+
+ cls._cleanup = [
+ cls.service_offering,
+ cls.disk_offering
+ ]
+ return
+
+ @classmethod
+ def tearDownClass(cls):
+ try:
+ # Cleanup resources used
+ cleanup_resources(cls.api_client, cls._cleanup)
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+ return
+
+ def setUp(self):
+ self.apiclient = self.testClient.getApiClient()
+ self.dbclient = self.testClient.getDbConnection()
+ self.cleanup = []
+
+ if self.unsupportedHypervisor:
+ self.skipTest("Skipping test because unsupported hypervisor: %s" %
+ self.hypervisor)
+
+
+ # Create VMs, NAT Rules etc
+ self.account = Account.create(
+ self.apiclient,
+ self.services["account"],
+ domainid=self.domain.id
+ )
+ self.cleanup.append(self.account)
+ self.virtual_machine_with_disk = VirtualMachine.create(
+ self.api_client,
+ self.services["small"],
+ templateid=self.template.id,
+ accountid=self.account.name,
+ domainid=self.account.domainid,
+ serviceofferingid=self.service_offering.id,
+ mode=self.zone.networktype
+ )
+ return
+
+ def tearDown(self):
+ try:
+ # Clean up, terminate the created instance, volumes and snapshots
+ cleanup_resources(self.apiclient, self.cleanup)
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+ return
+
+ @attr(speed="slow")
+ @attr(tags=["advanced", "advancedns", "smoke"], required_hardware="true")
+ def test_01_snapshot_data_disk(self):
+ """Test Snapshot Data Disk
+ """
+
+ volume = list_volumes(
+ self.apiclient,
+ virtualmachineid=self.virtual_machine_with_disk.id,
+ type='DATADISK',
+ listall=True
+ )
+ self.assertEqual(
+ isinstance(volume, list),
+ True,
+ "Check list response returns a valid list"
+ )
+
+ self.debug("Creating a Snapshot from data volume: %s" % volume[0].id)
+ snapshot = Snapshot.create(
+ self.apiclient,
+ volume[0].id,
+ account=self.account.name,
+ domainid=self.account.domainid,
+ asyncbackup=True
+ )
+ snapshots = list_snapshots(
+ self.apiclient,
+ id=snapshot.id
+ )
+ self.assertEqual(
+ isinstance(snapshots, list),
+ True,
+ "Check list response returns a valid list"
+ )
+ self.assertNotEqual(
+ snapshots,
+ None,
+ "Check if result exists in list item call"
+ )
+ self.assertEqual(
+ snapshots[0].id,
+ snapshot.id,
+ "Check resource id in list resources call"
+ )
+ self.assertEqual(
+ snapshot.state,
+ "BackingUp",
+ "Check resource state in list resources call"
+ )
+ return
diff --git a/test/integration/component/test_vpn_users.py b/test/integration/component/test_vpn_users.py
index 103ff1c0fca..97849045018 100644
--- a/test/integration/component/test_vpn_users.py
+++ b/test/integration/component/test_vpn_users.py
@@ -79,7 +79,7 @@ def __init__(self):
},
"vpn_user": {
"username": "test",
- "password": "p@a#s=s.w_o-r+d",
+ "password": "p@as=s.w_o-r+d",
},
"natrule": {
"privateport": 1701,
diff --git a/test/integration/plugins/nuagevsp/nuageTestCase.py b/test/integration/plugins/nuagevsp/nuageTestCase.py
index c673a9b31c4..e9edaac18e1 100644
--- a/test/integration/plugins/nuagevsp/nuageTestCase.py
+++ b/test/integration/plugins/nuagevsp/nuageTestCase.py
@@ -51,6 +51,7 @@
import sys
import time
from retry import retry
+from nuage_vsp_statistics import VsdDataCollector
class needscleanup(object):
@@ -848,6 +849,34 @@ def validate_PublicIPAddress(self, public_ip, network, static_nat=False,
self.debug("Successfully validated the assignment and state of public "
"IP address - %s" % public_ip.ipaddress.ipaddress)
+ # verify_VRWithoutPublicIPNIC - Verifies that the given Virtual Router has
+ # no public IP and NIC
+ def verify_VRWithoutPublicIPNIC(self, vr):
+ """Verifies VR without Public IP and NIC"""
+ self.debug("Verifies that there is no public IP and NIC in Virtual "
+ "Router - %s" % vr.name)
+ self.assertEqual(vr.publicip, None,
+ "Virtual router has public IP"
+ )
+ for nic in vr.nic:
+ self.assertNotEqual(nic.traffictype, "Public",
+ "Virtual router has public NIC"
+ )
+ self.debug("Successfully verified that there is no public IP and NIC "
+ "in Virtual Router - %s" % vr.name)
+
+ def verify_vpc_has_no_src_nat(self, vpc, account=None):
+ if not account:
+ account = self.account
+ self.debug("Verify that there is no src NAT ip address "
+ "allocated for the vpc")
+ src_nat_ip = PublicIPAddress.list(
+ self.api_client,
+ vpcid=vpc.id,
+ issourcenat=True,
+ account=account.name)
+ self.assertEqual(src_nat_ip, None, "VPC has a source NAT ip!")
+
# VSD verifications; VSD is a programmable policy and analytics engine of
# Nuage VSP SDN platform
@@ -984,10 +1013,10 @@ def verify_vsd_object_status(self, cs_object, stopped):
expected_status = cs_object.state.upper() if not stopped \
else "DELETE_PENDING"
tries = 0
- while (vsd_object.status != expected_status) and (tries < 10):
+ while (vsd_object.status != expected_status) and (tries < 120):
self.debug("Waiting for the CloudStack object " + cs_object.name +
" to be fully resolved in VSD...")
- time.sleep(30)
+ time.sleep(5)
self.debug("Rechecking the CloudStack object " + cs_object.name +
" status in VSD...")
vsd_object = self.vsd.get_vm(
diff --git a/test/integration/plugins/nuagevsp/nuage_test_data.py b/test/integration/plugins/nuagevsp/nuage_test_data.py
new file mode 100644
index 00000000000..7f3f3a2dfbf
--- /dev/null
+++ b/test/integration/plugins/nuagevsp/nuage_test_data.py
@@ -0,0 +1,2050 @@
+#t Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+test_data = {
+ "region": {
+ "regionid": "2",
+ "regionname": "Region2",
+ "regionendpoint": "http://region2:8080/client"
+ },
+ "zone": "NA",
+ "hypervisor": "XenServer",
+ "deleteDC": True,
+ "vdomain": {
+ "name": "domain"
+ },
+ "domain": {"name": "domain"},
+ "email": "test@test.com",
+ "gateway": "172.1.1.1",
+ "netmask": "255.255.255.0",
+ "startip": "172.1.1.10",
+ "endip": "172.1.1.20",
+ "regionid": "1",
+ "vlan": "10",
+ "isportable": "true",
+
+ "project": {
+ "name": "Project",
+ "displaytext": "Test project"
+ },
+ "publiciprange": {
+ "gateway": "",
+ "netmask": "",
+ "startip": "",
+ "endip": "",
+ "forvirtualnetwork": "true",
+ "vlan": "",
+ "zoneid": ""
+ },
+ "private_gateway": {
+ "ipaddress": "172.16.1.2",
+ "gateway": "172.16.1.1",
+ "netmask": "255.255.255.0",
+ "vlan": "10",
+ "name": "test_private_gateway"
+ },
+ "account": {
+ "email": "test-account@test.com",
+ "firstname": "test",
+ "lastname": "test",
+ "username": "test-account",
+ "password": "password"
+ },
+ "account2": {
+ "email": "test-account2@test.com",
+ "firstname": "test2",
+ "lastname": "test2",
+ "username": "test-account2",
+ "password": "password"
+ },
+ "small": {
+ "displayname": "testserver",
+ "username": "root",
+ "password": "password",
+ "ssh_port": 22,
+ "hypervisor": "XenServer",
+ "privateport": 22,
+ "publicport": 22,
+ "protocol": 'TCP',
+ },
+ "service_offering": {
+ "name": "Tiny Instance",
+ "displaytext": "Tiny Instance",
+ "cpunumber": 1,
+ "cpuspeed": 256, # in MHz
+ "memory": 256, # In MBs
+ },
+ "service_offerings": {
+ "tiny": {
+ "name": "Tiny Instance",
+ "displaytext": "Tiny Instance",
+ "cpunumber": 1,
+ "cpuspeed": 100,
+ "memory": 128,
+ },
+ "small": {
+ "name": "Small Instance",
+ "displaytext": "Small Instance",
+ "cpunumber": 1,
+ "cpuspeed": 100,
+ "memory": 256
+ },
+ "medium": {
+ "name": "Medium Instance",
+ "displaytext": "Medium Instance",
+ "cpunumber": 1,
+ "cpuspeed": 100,
+ "memory": 256,
+ },
+ "big": {
+ "name": "BigInstance",
+ "displaytext": "BigInstance",
+ "cpunumber": 1,
+ "cpuspeed": 100,
+ "memory": 512,
+ },
+ "large": {
+ "name": "LargeInstance",
+ "displaytext": "LargeInstance",
+ "cpunumber": 1,
+ "cpuspeed": 1024,
+ "memory": 2048,
+ },
+ "hasmall": {
+ "name": "HA Small Instance",
+ "displaytext": "HA Small Instance",
+ "cpunumber": 1,
+ "cpuspeed": 100,
+ "memory": 256,
+ "hosttags": "ha",
+ "offerha": True,
+ },
+ "taggedsmall": {
+ "name": "Tagged Small Instance",
+ "displaytext": "Tagged Small Instance",
+ "cpunumber": 1,
+ "cpuspeed": 100,
+ "memory": 256,
+ "hosttags": "vmsync",
+ },
+ },
+ "service_offering_h1": {
+ "name": "Tagged h1 Small Instance",
+ "displaytext": "Tagged h1 Small Instance",
+ "cpunumber": 1,
+ "cpuspeed": 100,
+ "memory": 256,
+ "hosttags": "h1"
+ },
+ "service_offering_h2": {
+ "name": "Tagged h2 Small Instance",
+ "displaytext": "Tagged h2 Small Instance",
+ "cpunumber": 1,
+ "cpuspeed": 100,
+ "memory": 256,
+ "hosttags": "h2"
+ },
+ "disk_offering": {
+ "name": "Disk offering",
+ "displaytext": "Disk offering",
+ "disksize": 1
+ },
+ 'resized_disk_offering': {
+ "displaytext": "Resized",
+ "name": "Resized",
+ "disksize": 3
+ },
+ 'disk_offering_shared_5GB': {
+ "displaytext": "disk_offering_shared_5GB",
+ "name": "disk_offering_shared_5GB",
+ "disksize": 5
+ },
+ 'disk_offering_shared_15GB': {
+ "displaytext": "disk_offering_shared_5GB",
+ "name": "disk_offering_shared_5GB",
+ "disksize": 15
+ },
+ "network": {
+ "name": "Test Network",
+ "displaytext": "Test Network",
+ "acltype": "Account",
+ },
+ "network2": {
+ "name": "Test Network Shared",
+ "displaytext": "Test Network Shared",
+ "vlan": 1201,
+ "gateway": "172.16.15.1",
+ "netmask": "255.255.255.0",
+ "startip": "172.16.15.21",
+ "endip": "172.16.15.41",
+ "acltype": "Account",
+ },
+ "network_offering": {
+ "name": 'Test Network offering',
+ "displaytext": 'Test Network offering',
+ "guestiptype": 'Isolated',
+ "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding',
+ "traffictype": 'GUEST',
+ "availability": 'Optional',
+ "serviceProviderList": {
+ "Dhcp": 'VirtualRouter',
+ "Dns": 'VirtualRouter',
+ "SourceNat": 'VirtualRouter',
+ "PortForwarding": 'VirtualRouter',
+ },
+ },
+ "nw_off_isolated_netscaler": {
+ "name": 'Netscaler',
+ "displaytext": 'Netscaler',
+ "guestiptype": 'Isolated',
+ "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat',
+ "traffictype": 'GUEST',
+ "availability": 'Optional',
+ "serviceProviderList": {
+ "Dhcp": 'VirtualRouter',
+ "Dns": 'VirtualRouter',
+ "SourceNat": 'VirtualRouter',
+ "PortForwarding": 'VirtualRouter',
+ "Vpn": 'VirtualRouter',
+ "Firewall": 'VirtualRouter',
+ "Lb": 'Netscaler',
+ "UserData": 'VirtualRouter',
+ "StaticNat": 'VirtualRouter',
+ },
+ },
+ "nw_off_isolated_persistent": {
+ "name": 'Test Nw off isolated persistent',
+ "displaytext": 'Test Nw off isolated persistent',
+ "guestiptype": 'Isolated',
+ "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding',
+ "traffictype": 'GUEST',
+ "ispersistent": 'True',
+ "availability": 'Optional',
+ "serviceProviderList": {
+ "Dhcp": 'VirtualRouter',
+ "Dns": 'VirtualRouter',
+ "SourceNat": 'VirtualRouter',
+ "PortForwarding": 'VirtualRouter',
+ },
+ },
+ "nw_off_isolated_persistent_lb": {
+ "name": 'Test Nw off isolated persistent',
+ "displaytext": 'Test Nw off isolated persistent',
+ "guestiptype": 'Isolated',
+ "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Lb',
+ "traffictype": 'GUEST',
+ "ispersistent": 'True',
+ "availability": 'Optional',
+ "serviceProviderList": {
+ "Dhcp": 'VirtualRouter',
+ "Dns": 'VirtualRouter',
+ "SourceNat": 'VirtualRouter',
+ "PortForwarding": 'VirtualRouter',
+ "Lb": "VirtualRouter"
+ },
+ },
+ "isolated_network_offering": {
+ "name": "Network offering-DA services",
+ "displaytext": "Network offering-DA services",
+ "guestiptype": "Isolated",
+ "supportedservices":
+ "Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat",
+ "traffictype": "GUEST",
+ "availability": "Optional'",
+ "serviceProviderList": {
+ "Dhcp": "VirtualRouter",
+ "Dns": "VirtualRouter",
+ "SourceNat": "VirtualRouter",
+ "PortForwarding": "VirtualRouter",
+ "Vpn": "VirtualRouter",
+ "Firewall": "VirtualRouter",
+ "Lb": "VirtualRouter",
+ "UserData": "VirtualRouter",
+ "StaticNat": "VirtualRouter"
+ }
+ },
+ "network_offering_vlan": {
+ "name": 'Test Network offering',
+ "displaytext": 'Test Network offering',
+ "guestiptype": 'Isolated',
+ "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding',
+ "traffictype": 'GUEST',
+ "specifyvlan": 'False',
+ "availability": 'Optional',
+ "serviceProviderList": {
+ "Dhcp": 'VirtualRouter',
+ "Dns": 'VirtualRouter',
+ "SourceNat": 'VirtualRouter',
+ "PortForwarding": 'VirtualRouter',
+ },
+ },
+ "network_offering_without_sourcenat": {
+ "name": 'Test Network offering',
+ "displaytext": 'Test Network offering',
+ "guestiptype": 'Isolated',
+ "supportedservices": 'Dhcp,Dns,UserData',
+ "traffictype": 'GUEST',
+ "availability": 'Optional',
+ "serviceProviderList": {
+ "Dhcp": 'VirtualRouter',
+ "Dns": 'VirtualRouter',
+ "UserData": 'VirtualRouter',
+ },
+ },
+ "isolated_network": {
+ "name": "Isolated Network",
+ "displaytext": "Isolated Network"
+ },
+ "netscaler_VPX": {
+ "ipaddress": "10.223.240.174",
+ "username": "nsroot",
+ "password": "nsroot",
+ "networkdevicetype": "NetscalerVPXLoadBalancer",
+ "publicinterface": "1/1",
+ "privateinterface": "1/2",
+ "numretries": 2,
+ "lbdevicededicated": "True",
+ "lbdevicecapacity": 2,
+ "port": 22
+ },
+ "netscaler_network": {
+ "name": "Netscaler",
+ "displaytext": "Netscaler",
+ },
+ "network_without_acl": {
+ "name": "TestNetwork",
+ "displaytext": "TestNetwork",
+ },
+ "virtual_machine": {
+ "displayname": "Test VM",
+ "username": "root",
+ "password": "password",
+ "ssh_port": 22,
+ "privateport": 22,
+ "publicport": 22,
+ "protocol": "TCP",
+ "affinity": {
+ "name": "webvms",
+ "type": "host anti-affinity",
+ }
+ },
+ "virtual_machine_userdata": {
+ "displayname": "Test VM",
+ "username": "root",
+ "password": "password",
+ "ssh_port": 22,
+ "privateport": 22,
+ "publicport": 22,
+ "protocol": "TCP",
+ "affinity": {
+ "name": "webvms",
+ "type": "host anti-affinity",
+ },
+ "userdata": "This is sample data"
+ },
+ "virtual_machine2": {
+ "name": "testvm2",
+ "displayname": "Test VM2",
+ },
+ "virtual_machine3": {
+ "name": "testvm3",
+ "displayname": "Test VM3",
+ },
+ "shared_network": {
+ "name": "MySharedNetwork - Test",
+ "displaytext": "MySharedNetwork",
+ "vlan": "",
+ "gateway": "",
+ "netmask": "",
+ "startip": "",
+ "endip": "",
+ "acltype": "Domain",
+ "scope": "all"
+ },
+ "shared_network_offering": {
+ "name": "MySharedOffering-shared",
+ "displaytext": "MySharedOffering",
+ "guestiptype": "Shared",
+ "supportedservices": "Dhcp,Dns,UserData",
+ "specifyVlan": "False",
+ "specifyIpRanges": "False",
+ "traffictype": "GUEST",
+ "serviceProviderList": {
+ "Dhcp": "VirtualRouter",
+ "Dns": "VirtualRouter",
+ "UserData": "VirtualRouter"
+ }
+ },
+ "shared_network_offering_all_services": {
+ "name": "shared network offering with services enabled",
+ "displaytext": "Shared network offering",
+ "guestiptype": "Shared",
+ "supportedservices": "Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat",
+ "specifyVlan": "False",
+ "specifyIpRanges": "False",
+ "traffictype": "GUEST",
+ "serviceProviderList": {
+ "Dhcp": "VirtualRouter",
+ "Dns": "VirtualRouter",
+ "UserData": "VirtualRouter",
+ "SourceNat": "VirtualRouter",
+ "PortForwarding": "VirtualRouter",
+ "Vpn": "VirtualRouter",
+ "Firewall": "VirtualRouter",
+ "Lb": "VirtualRouter",
+ "UserData": "VirtualRouter",
+ "StaticNat": "VirtualRouter"
+ }
+ },
+ "shared_network_offering_sg": {
+ "name": "MySharedOffering-sg",
+ "displaytext": "MySharedOffering-sg",
+ "guestiptype": "Shared",
+ "supportedservices": "Dhcp,Dns,UserData,SecurityGroup",
+ "specifyVlan": "False",
+ "specifyIpRanges": "False",
+ "traffictype": "GUEST",
+ "serviceProviderList": {
+ "Dhcp": "VirtualRouter",
+ "Dns": "VirtualRouter",
+ "UserData": "VirtualRouter",
+ "SecurityGroup": "SecurityGroupProvider"
+ }
+ },
+ "shared_network_sg": {
+ "name": "Shared-Network-SG-Test",
+ "displaytext": "Shared-Network_SG-Test",
+ "networkofferingid": "1",
+ "vlan": "",
+ "gateway": "",
+ "netmask": "255.255.255.0",
+ "startip": "",
+ "endip": "",
+ "acltype": "Domain",
+ "scope": "all"
+ },
+ "vpc_offering": {
+ "name": "VPC off",
+ "displaytext": "VPC off",
+ "supportedservices":
+ "Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat,NetworkACL"
+ },
+ "vpc_offering_multi_lb": {
+ "name": "VPC offering with multiple Lb service providers",
+ "displaytext": "VPC offering with multiple Lb service providers",
+ "supportedservices": "Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat,NetworkACL",
+ "serviceProviderList": {
+ "Vpn": 'VpcVirtualRouter',
+ "Dhcp": 'VpcVirtualRouter',
+ "Dns": 'VpcVirtualRouter',
+ "SourceNat": 'VpcVirtualRouter',
+ "Lb": ["InternalLbVm", "VpcVirtualRouter"],
+ "PortForwarding": 'VpcVirtualRouter',
+ "UserData": 'VpcVirtualRouter',
+ "StaticNat": 'VpcVirtualRouter',
+ "NetworkACL": 'VpcVirtualRouter'
+ }
+ },
+ "vpc": {
+ "name": "TestVPC",
+ "displaytext": "TestVPC",
+ "cidr": "10.0.0.1/24"
+ },
+ "vpc_network_domain": {
+ "name": "TestVPC",
+ "displaytext": "TestVPC",
+ "cidr": '10.0.0.1/24',
+ "network_domain": "TestVPC"
+ },
+ "clusters": {
+ 0: {
+ "clustername": "Xen Cluster",
+ "clustertype": "CloudManaged",
+ "hypervisor": "XenServer",
+ },
+ 1: {
+ "clustername": "KVM Cluster",
+ "clustertype": "CloudManaged",
+ "hypervisor": "KVM",
+ },
+ 2: {
+ "hypervisor": 'VMware',
+ "clustertype": 'ExternalManaged',
+ "username": 'administrator',
+ "password": 'fr3sca',
+ "url": 'http://192.168.100.17/CloudStack-Clogeny-Pune/Pune-1',
+ "clustername": 'VMWare Cluster',
+ },
+ },
+ "hosts": {
+ "xenserver": {
+ "hypervisor": 'XenServer',
+ "clustertype": 'CloudManaged',
+ "url": 'http://192.168.100.211',
+ "username": "root",
+ "password": "fr3sca",
+ },
+ "kvm": {
+ "hypervisor": 'KVM',
+ "clustertype": 'CloudManaged',
+ "url": 'http://192.168.100.212',
+ "username": "root",
+ "password": "fr3sca",
+ },
+ "vmware": {
+ "hypervisor": 'VMware',
+ "clustertype": 'ExternalManaged',
+ "url": 'http://192.168.100.203',
+ "username": "administrator",
+ "password": "fr3sca",
+ },
+ },
+ "network_offering_shared": {
+ "name": 'Test Network offering shared',
+ "displaytext": 'Test Network offering Shared',
+ "guestiptype": 'Shared',
+ "supportedservices": 'Dhcp,Dns,UserData',
+ "traffictype": 'GUEST',
+ "specifyVlan": "True",
+ "specifyIpRanges": "True",
+ "serviceProviderList": {
+ "Dhcp": 'VirtualRouter',
+ "Dns": 'VirtualRouter',
+ "UserData": 'VirtualRouter',
+ },
+ },
+ "nw_off_isolated_RVR": {
+ "name": "Network offering-RVR services",
+ "displaytext": "Network off-RVR services",
+ "guestiptype": "Isolated",
+ "supportedservices": "Vpn,Dhcp,Dns,SourceNat,PortForwarding,Firewall,Lb,UserData,StaticNat",
+ "traffictype": "GUEST",
+ "availability": "Optional",
+ "ispersistent": "False",
+ "serviceProviderList": {
+ "Vpn": "VirtualRouter",
+ "Dhcp": "VirtualRouter",
+ "Dns": "VirtualRouter",
+ "SourceNat": "VirtualRouter",
+ "PortForwarding": "VirtualRouter",
+ "Firewall": "VirtualRouter",
+ "Lb": "VirtualRouter",
+ "UserData": "VirtualRouter",
+ "StaticNat": "VirtualRouter"
+ },
+ "serviceCapabilityList": {
+ "SourceNat": {
+ "SupportedSourceNatTypes": "peraccount",
+ "RedundantRouter": "true"
+ },
+ "lb": {
+ "SupportedLbIsolation": "dedicated"
+ }
+ }
+ },
+ "nw_off_persistent_RVR": {
+ "name": 'Network offering-RVR services',
+ "displaytext": 'Network off-RVR services',
+ "guestiptype": 'Isolated',
+ "supportedservices":
+ 'Vpn,Dhcp,Dns,SourceNat,PortForwarding,Firewall,Lb,UserData,StaticNat',
+ "traffictype": 'GUEST',
+ "ispersistent": 'True',
+ "availability": 'Optional',
+ "serviceProviderList": {
+ "Vpn": 'VirtualRouter',
+ "Dhcp": 'VirtualRouter',
+ "Dns": 'VirtualRouter',
+ "SourceNat": 'VirtualRouter',
+ "PortForwarding": 'VirtualRouter',
+ "Firewall": 'VirtualRouter',
+ "Lb": 'VirtualRouter',
+ "UserData": 'VirtualRouter',
+ "StaticNat": 'VirtualRouter',
+ },
+ "serviceCapabilityList": {
+ "SourceNat": {
+ "SupportedSourceNatTypes": "peraccount",
+ "RedundantRouter": "true",
+ },
+ "lb": {
+ "SupportedLbIsolation": "dedicated"
+ },
+ },
+ },
+ "nw_offering_isolated_vpc": {
+ "name": "Isolated Network for VPC",
+ "displaytext": "Isolated Network for VPC",
+ "guestiptype": "Isolated",
+ "supportedservices": "Dhcp,Dns,SourceNat,PortForwarding,Vpn,UserData,StaticNat,NetworkACL,Lb",
+ "traffictype": "GUEST",
+ "availability": "Optional",
+ "ispersistent": "False",
+ "useVpc": "on",
+ "serviceProviderList": {
+ "Dhcp": "VpcVirtualRouter",
+ "Dns": "VpcVirtualRouter",
+ "SourceNat": "VpcVirtualRouter",
+ "PortForwarding": "VpcVirtualRouter",
+ "Vpn": "VpcVirtualRouter",
+ "UserData": "VpcVirtualRouter",
+ "StaticNat": "VpcVirtualRouter",
+ "NetworkACL": "VpcVirtualRouter",
+ "Lb": "VpcVirtualRouter"
+ }
+ },
+ "nw_off_persistent_VPCVR_LB": {
+ "name": "Persistent Network VPC with LB",
+ "displaytext": "Persistent Network VPC No LB",
+ "guestiptype": "Isolated",
+ "supportedservices": "Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat,NetworkACL",
+ "traffictype": "GUEST",
+ "availability": "Optional",
+ "ispersistent": "True",
+ "useVpc": "on",
+ "serviceProviderList": {
+ "Dhcp": "VpcVirtualRouter",
+ "Dns": "VpcVirtualRouter",
+ "SourceNat": "VpcVirtualRouter",
+ "PortForwarding": "VpcVirtualRouter",
+ "Vpn": "VpcVirtualRouter",
+ "Lb": "VpcVirtualRouter",
+ "UserData": "VpcVirtualRouter",
+ "StaticNat": "VpcVirtualRouter",
+ "NetworkACL": "VpcVirtualRouter"
+ }
+ },
+ "nw_off_persistent_VPCVR_NoLB": {
+ "name": "Persistent Network VPC No LB",
+ "displaytext": "Persistent Network VPC No LB",
+ "guestiptype": "Isolated",
+ "supportedservices": "Dhcp,Dns,SourceNat,PortForwarding,Vpn,UserData,StaticNat,NetworkACL",
+ "traffictype": "GUEST",
+ "availability": "Optional",
+ "ispersistent": "True",
+ "useVpc": "on",
+ "serviceProviderList": {
+ "Dhcp": "VpcVirtualRouter",
+ "Dns": "VpcVirtualRouter",
+ "SourceNat": "VpcVirtualRouter",
+ "PortForwarding": "VpcVirtualRouter",
+ "Vpn": "VpcVirtualRouter",
+ "UserData": "VpcVirtualRouter",
+ "StaticNat": "VpcVirtualRouter",
+ "NetworkACL": "VpcVirtualRouter"
+ }
+ },
+ "nw_offering_shared_persistent": {
+ "name": "Network offering for Shared Persistent Network",
+ "displaytext": "Network offering-DA services",
+ "guestiptype": "Shared",
+ "supportedservices": "Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat",
+ "traffictype": "GUEST",
+ "availability": "Optional",
+ "ispersistent": "True",
+ "serviceProviderList": {
+ "Dhcp": "VirtualRouter",
+ "Dns": "VirtualRouter",
+ "SourceNat": "VirtualRouter",
+ "PortForwarding": "VirtualRouter",
+ "Vpn": "VirtualRouter",
+ "Firewall": "VirtualRouter",
+ "Lb": "VirtualRouter",
+ "UserData": "VirtualRouter",
+ "StaticNat": "VirtualRouter"
+ }
+ },
+ "fwrule": {
+ "startport": 22,
+ "endport": 22,
+ "cidr": "0.0.0.0/0",
+ "protocol": "TCP"
+ },
+ "nw_off_ncc_SharedSP": {
+ "name": 'SharedSP',
+ "displaytext": 'SharedSP',
+ "guestiptype": 'Isolated',
+ "supportedservices":
+ 'Dhcp,Dns,SourceNat,Lb,StaticNat',
+ "traffictype": 'GUEST',
+ "availability": 'Optional',
+ "serviceProviderList": {
+ "Dhcp": 'VirtualRouter',
+ "Dns": 'VirtualRouter',
+ "SourceNat": 'VirtualRouter',
+ "Lb": 'Netscaler',
+ "StaticNat": 'VirtualRouter'
+ }
+ },
+ "nw_off_ncc_DedicatedSP": {
+ "name": 'DedicatedSP',
+ "displaytext": 'DedicatedSP',
+ "guestiptype": 'Isolated',
+ "supportedservices":
+ 'Dhcp,Dns,SourceNat,Lb,StaticNat',
+ "traffictype": 'GUEST',
+ "availability": 'Optional',
+ "serviceProviderList": {
+ "Dhcp": 'VirtualRouter',
+ "Dns": 'VirtualRouter',
+ "SourceNat": 'VirtualRouter',
+ "Lb": 'Netscaler',
+ "StaticNat": 'VirtualRouter'
+ }
+ },
+ "NCC": {
+ "NCCIP": '10.102.195.215',
+ },
+ "NSShared": {
+ "NSIP": '10.102.195.210',
+ },
+ "NSDedicated": {
+ "NSIP": '10.102.195.212'
+ },
+ "servicepackage_shared": {
+ "name": "SharedSP",
+ },
+ "servicepackage_dedicated": {
+ "name": "DedicatedSP",
+ },
+
+ "nw_off_isolated_persistent_netscaler": {
+ "name": 'Netscaler',
+ "displaytext": 'Netscaler',
+ "guestiptype": 'Isolated',
+ "supportedservices":
+ 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat',
+ "traffictype": 'GUEST',
+ "ispersistent": 'True',
+ "availability": 'Optional',
+ "serviceProviderList": {
+ "Dhcp": 'VirtualRouter',
+ "Dns": 'VirtualRouter',
+ "SourceNat": 'VirtualRouter',
+ "PortForwarding": 'VirtualRouter',
+ "Vpn": 'VirtualRouter',
+ "Firewall": 'VirtualRouter',
+ "Lb": 'Netscaler',
+ "UserData": 'VirtualRouter',
+ "StaticNat": 'VirtualRouter',
+ },
+
+ },
+ "network_acl_rule": {
+ "protocol": "TCP",
+ "traffictype": "ingress",
+ "cidrlist": "0.0.0.0/0",
+ "startport": "1",
+ "endport": "1"
+ },
+ "network_offering_internal_lb": {
+ "name": "Network offering for internal lb service",
+ "displaytext": "Network offering for internal lb service",
+ "guestiptype": "Isolated",
+ "traffictype": "Guest",
+ "supportedservices":
+ "Vpn,Dhcp,Dns,Lb,UserData,SourceNat,StaticNat,PortForwarding,NetworkACL",
+ "serviceProviderList": {
+ "Dhcp": "VpcVirtualRouter",
+ "Dns": "VpcVirtualRouter",
+ "Vpn": "VpcVirtualRouter",
+ "UserData": "VpcVirtualRouter",
+ "Lb": "InternalLbVM",
+ "SourceNat": "VpcVirtualRouter",
+ "StaticNat": "VpcVirtualRouter",
+ "PortForwarding": "VpcVirtualRouter",
+ "NetworkACL": "VpcVirtualRouter",
+ },
+ "serviceCapabilityList": {
+ "SourceNat": {"SupportedSourceNatTypes": "peraccount"},
+ "Lb": {"lbSchemes": "internal", "SupportedLbIsolation": "dedicated"}
+ }
+ },
+ "natrule": {
+ "privateport": 22,
+ "publicport": 22,
+ "protocol": "TCP"
+ },
+ "natrulerange": {
+ "privateport": 70,
+ "privateendport": 75,
+ "publicport": 70,
+ "publicendport": 75,
+ "protocol": "TCP"
+ },
+ "updatenatrulerange": {
+ "privateport": 50,
+ "privateendport": 55,
+ },
+ "egress_80": {
+ "startport": 80,
+ "endport": 80,
+ "protocol": "TCP",
+ "cidrlist": ["0.0.0.0/0"]
+ },
+ "lbrule": {
+ "name": "SSH",
+ "alg": "roundrobin",
+ "privateport": 22,
+ "publicport": 2222,
+ "protocol": 'TCP'
+ },
+ "vpclbrule": {
+ "name": "SSH",
+ "alg": "roundrobin",
+ "privateport": 22,
+ "publicport": 22,
+ "protocol": 'TCP'
+ },
+ "internal_lbrule": {
+ "name": "SSH",
+ "algorithm": "roundrobin",
+ # Algorithm used for load balancing
+ "sourceport": 22,
+ "instanceport": 22,
+ "scheme": "internal",
+ "protocol": "TCP",
+ "cidrlist": '0.0.0.0/0',
+ },
+ "internal_lbrule_http": {
+ "name": "HTTP",
+ "algorithm": "roundrobin",
+ # Algorithm used for load balancing
+ "sourceport": 80,
+ "instanceport": 80,
+ "scheme": "internal",
+ "protocol": "TCP",
+ "cidrlist": '0.0.0.0/0',
+ },
+ "http_rule": {
+ "privateport": 80,
+ "publicport": 80,
+ "startport": 80,
+ "endport": 80,
+ "protocol": "TCP",
+ "cidrlist": '0.0.0.0/0',
+ },
+ "dns_rule": {
+ "privateport": 53,
+ "publicport": 53,
+ "startport": 53,
+ "endport": 53,
+ "protocol": "UDP",
+ "cidrlist": '0.0.0.0/0',
+ },
+ "icmprule": {
+ "icmptype": -1,
+ "icmpcode": -1,
+ "cidrlist": "0.0.0.0/0",
+ "protocol": "ICMP"
+ },
+ "iso": {
+ "displaytext": "Test ISO",
+ "name": "ISO",
+ "url": "http://people.apache.org/~tsp/dummy.iso",
+ "bootable": False,
+ "ispublic": False,
+ "ostype": "Other (64-bit)",
+ },
+ "iso1": {
+ "displaytext": "Test ISO 1",
+ "name": "ISO 1",
+ "url": "http://people.apache.org/~tsp/dummy.iso",
+ "isextractable": True,
+ "isfeatured": True,
+ "ispublic": True,
+ "ostype": "CentOS 5.6 (64-bit)",
+ },
+ "iso2": {
+ "displaytext": "Test ISO 2",
+ "name": "ISO 2",
+ "url": "http://people.apache.org/~tsp/dummy.iso",
+ "isextractable": True,
+ "isfeatured": True,
+ "ispublic": True,
+ "ostype": "CentOS 5.6 (64-bit)",
+ "mode": 'HTTP_DOWNLOAD',
+ },
+ "isfeatured": True,
+ "ispublic": True,
+ "isextractable": True,
+ "bootable": True,
+ "passwordenabled": True,
+
+ "template": {
+ "displaytext": "xs",
+ "name": "xs",
+ "passwordenabled": False,
+ "ostype": "CentOS 5.6 (64-bit)"
+
+ },
+ "coreos_volume": {
+ "diskname": "Volume_core",
+ "urlvmware":"http://dl.openvm.eu/cloudstack/coreos/x86_64/coreos_production_cloudstack_image-vmware.ova",
+ "urlxen":"http://dl.openvm.eu/cloudstack/coreos/x86_64/coreos_production_cloudstack_image-xen.vhd.bz2",
+ "urlkvm": "http://dl.openvm.eu/cloudstack/coreos/x86_64/" \
+ "coreos_production_cloudstack_image-kvm.qcow2.bz2",
+ "urlhyperv":"http://dl.openvm.eu/cloudstack/coreos/x86_64/coreos_production_cloudstack_image-hyperv.vhd.zip"
+ },
+ "CentOS6.3template": {
+ "displaytext": "Centos",
+ "name": "Centos",
+ "passwordenabled": False,
+ "ostype": "CentOS 6.3 (64-bit)",
+ "url": "http://people.apache.org/~sanjeev/centos63.ova",
+ "format": "OVA",
+ "ispublic": "true"
+ },
+ "CentOS7template": {
+ "displaytext": "Centos",
+ "name": "Centos",
+ "passwordenabled": False,
+ "isdynamicallyscalable":True,
+ "ostype": "CentOS 7",
+ "url": "http://dl.openvm.eu/cloudstack/centos/vanilla/7/x86_64/CentOS-7-x86_64-vanilla-xen.vhd.bz2",
+ "format": "VHD",
+ "ispublic": "true",
+ "hypervisor":"Xenserver"
+ },
+ "Rhel7template": {
+ "displaytext": "Rhel",
+ "name": "Rhel",
+ "passwordenabled": False,
+ "ostype": "Red Hat Enterprise Linux 7",
+ "format": "OVA",
+ "ispublic": "true"
+ },
+ "template_2": {
+ "displaytext": "Public Template",
+ "name": "Public template",
+ "ostype": "CentOS 5.6 (64-bit)",
+ "isfeatured": True,
+ "ispublic": True,
+ "isextractable": True,
+ "mode": "HTTP_DOWNLOAD",
+ "templatefilter": "self"
+ },
+ "Windows 7 (64-bit)": {
+ "displaytext": "Windows 7 (64-bit)",
+ "name": "Windows 7 (64-bit)",
+ "passwordenabled": False,
+ "url": "http://people.apache.org/~sanjeev/windows7.vhd",
+ "format": "VHD",
+ "ostype": "Windows 7 (64-bit)",
+ "ispublic": "true",
+ "hypervisor": "XenServer"
+ },
+ "Windows Server 2012": {
+ "displaytext": "Windows Server 2012",
+ "name": "Windows Server 2012",
+ "passwordenabled": False,
+ "format": "OVA",
+ "ostype": "Windows Server 2012 (64-bit)",
+ "ispublic": "true",
+ "hypervisor": "Vmware"
+ },
+ "privatetemplate": {
+ "displaytext": "Public Template",
+ "name": "Public template",
+ "ostype": "CentOS 5.6 (64-bit)",
+ "isfeatured": True,
+ "ispublic": False,
+ "isextractable": True,
+ "mode": "HTTP_DOWNLOAD",
+ "templatefilter": "self"
+ },
+ "volume_from_snapshot": {
+ "diskname": 'Volume from snapshot',
+ "size": "1",
+ "zoneid": ""
+ },
+ "templatefilter": 'self',
+ "templates": {
+ "displaytext": 'Template',
+ "name": 'Template',
+ "ostype": "CentOS 5.3 (64-bit)",
+ "templatefilter": 'self',
+ },
+ "win2012template": {
+ "displaytext": "win2012",
+ "name": "win2012",
+ "passwordenabled": False,
+ "url": "http://people.apache.org/~sanjeev/new-test-win.ova",
+ "format": "OVA",
+ "ostype": "Windows 8 (64-bit)",
+ },
+ "rhel60template": {
+ "displaytext": "Rhel60",
+ "name": "Rhel60",
+ "passwordenabled": False,
+ "url": "http://people.apache.org/~sanjeev/Rhel6-64bit.ova",
+ "format": "OVA",
+ "ostype": "Red Hat Enterprise Linux 6.0 (64-bit)"
+ },
+ "security_group": {"name": "custom_Sec_Grp"},
+ "ingress_rule": {
+ "protocol": "TCP",
+ "startport": "22",
+ "endport": "22",
+ "cidrlist": "0.0.0.0/0"
+ },
+ "ingress_rule_ICMP": {
+ "name": 'ICMP',
+ "protocol": 'ICMP',
+ "startport": -1,
+ "endport": -1,
+ "cidrlist": '0.0.0.0/0',
+ },
+ "vpncustomergateway": {
+ "ipsecpsk": "secreatKey",
+ "ikepolicy": "aes128-sha1",
+ "ikelifetime": "86400",
+ "esppolicy": "aes128-sha1",
+ "epslifetime": "3600",
+ "dpd": "false"
+ },
+ "vlan_ip_range": {
+ "startip": "",
+ "endip": "",
+ "netmask": "",
+ "gateway": "",
+ "forvirtualnetwork": "false",
+ "vlan": "untagged",
+ },
+ "ostype": "CoreOS",
+ "sleep": 90,
+ "timeout": 10,
+ "page": 1,
+ "pagesize": 2,
+ "listall": 'true',
+ "advanced_sg": {
+ "zone": {
+ "name": "",
+ "dns1": "8.8.8.8",
+ "internaldns1": "192.168.100.1",
+ "networktype": "Advanced",
+ "securitygroupenabled": "true"
+ },
+ "securitygroupenabled": "true"
+ },
+ "vlan": "10",
+ "portableiprange_vlan": {
+ "part": ["4090-4091", "4092-4095"],
+ "full": "4090-4095"
+ },
+ "nfs": {
+ "url": "nfs://nfs/export/automation/1/testprimary",
+ "name": "Primary XEN"
+ },
+ "nfs2": {
+ "url": "nfs://nfs/export/automation/1/testprimary2",
+ "name": "Primary XEN 2"
+ },
+ "iscsi": {
+ "url":
+ "iscsi://192.168.100.21/iqn.2012-01.localdomain.clo-cstack-cos6:iser/1",
+ "name": "Primary iSCSI"
+ },
+ "volume": {"diskname": "Test Volume",
+ "size": 1
+ },
+ "volume_write_path": {
+ "diskname": "APP Data Volume",
+ "size": 1, # in GBs
+ "xenserver": {"rootdiskdevice":"/dev/xvda",
+ "datadiskdevice_1": '/dev/xvdb',
+ "datadiskdevice_2": '/dev/xvdc', # Data Disk
+ },
+ "kvm": {"rootdiskdevice": "/dev/vda",
+ "datadiskdevice_1": "/dev/vdb",
+ "datadiskdevice_2": "/dev/vdc"
+ },
+ "vmware": {"rootdiskdevice": "/dev/hda",
+ "datadiskdevice_1": "/dev/hdb",
+ "datadiskdevice_2": "/dev/hdc"
+ }
+ },
+ "data_write_paths": {
+ "mount_dir": "/mnt/tmp",
+ "sub_dir": "test",
+ "sub_lvl_dir1": "test1",
+ "sub_lvl_dir2": "test2",
+ "random_data": "random.data",
+ },
+ "custom_volume": {
+ "customdisksize": 1,
+ "diskname": "Custom disk",
+ },
+ "recurring_snapshot": {
+ "maxsnaps": 2,
+ "timezone": "US/Arizona",
+ "schedule": 1
+ },
+ "volume_offerings": {
+ 0: {"diskname": "TestDiskServ"},
+ },
+ "diskdevice": ['/dev/vdc', '/dev/vdb', '/dev/hdb', '/dev/hdc',
+ '/dev/xvdd', '/dev/cdrom', '/dev/sr0', '/dev/cdrom1'],
+
+ # test_vpc_vpn.py
+ "vpn_user": {
+ "username": "test",
+ "password": "password",
+ },
+ "vpc": {
+ "name": "vpc_vpn",
+ "displaytext": "vpc-vpn",
+ "cidr": "10.1.1.0/24"
+ },
+ "ntwk": {
+ "name": "tier1",
+ "displaytext": "vpc-tier1",
+ "gateway": "10.1.1.1",
+ "netmask": "255.255.255.192"
+ },
+ "vpc2": {
+ "name": "vpc2_vpn",
+ "displaytext": "vpc2-vpn",
+ "cidr": "10.2.1.0/24"
+ },
+ "ntwk2": {
+ "name": "tier2",
+ "displaytext": "vpc-tier2",
+ "gateway": "10.2.1.1",
+ "netmask": "255.255.255.192"
+ },
+ "privateport": 22,
+ "publicport": 22,
+ "protocol": 'TCP',
+ "forvirtualnetwork": "true",
+ "customdisksize": 1,
+ "diskname": "Test Volume",
+ "sparse": {
+ "name": "Sparse Type Disk offering",
+ "displaytext":
+ "Sparse Type Disk offering",
+ "disksize": 1, # in GB
+ "provisioningtype": "sparse"
+ },
+ "fat": {
+ "name": "Fat Type Disk offering",
+ "displaytext":
+ "Fat Type Disk offering",
+ "disksize": 1, # in GB
+ "provisioningtype": "fat"
+ },
+ "sparse_disk_offering": {
+ "displaytext": "Sparse",
+ "name": "Sparse",
+ "provisioningtype": "sparse",
+ "disksize": 1
+ },
+ "host_anti_affinity": {
+ "name": "hostantiaffinity",
+ "type": "host anti-affinity",
+ },
+ "vgpu": {
+ "disk_offering": {
+ "displaytext": "Small",
+ "name": "Small",
+ "disksize": 1
+ },
+ "templateregister1": {
+ "displaytext": "win8withpv",
+ "name": "win8withpv",
+ "passwordenabled": False,
+ "url": "http://pleaseupdateURL/dummy.vhd",
+ "format": "VHD",
+ "ostype": "Windows 8 (64-bit)",
+ "ispublic": "true",
+ "hypervisor": "XenServer"
+ },
+ "Windows 8 (64-bit)": {
+ "displaytext": "Windows 8 (64-bit)",
+ "name": "win8withpv",
+ "passwordenabled": False,
+ "url": "http://pleaseupdateURL/dummy.vhd",
+ "format": "VHD",
+ "ostype": "Windows 8 (64-bit)",
+ "ispublic": "true",
+ "hypervisor": "XenServer"
+ },
+ "Windows Server 2012 (64-bit)": {
+ "displaytext": "Windows Server 2012 (64-bit)",
+ "name": "Windows Server 2012 (64-bit)",
+ "passwordenabled": False,
+ "url": "http://pleaseupdateURL/dummy.vhd",
+ "format": "VHD",
+ "ostype": "Windows Server 2012 (64-bit)",
+ "ispublic": "true",
+ "hypervisor": "XenServer"
+ },
+
+ "Windows 7 (64-bit)": {
+ "displaytext": "Windows 7 (64-bit)",
+ "name": "Windows 7 (64-bit)",
+ "passwordenabled": False,
+ "url": "http://pleaseupdateURL/dummy.vhd",
+ "format": "VHD",
+ "ostype": "Windows 7 (64-bit)",
+ "ispublic": "true",
+ "hypervisor": "XenServer"
+ },
+ "RHEL 7 (64-bit)": {
+ "displaytext": "RHEL7 (64-bit)",
+ "name": "RHEL 7 Insta1",
+ "passwordenabled": False,
+ "url": "http://people.apache.org/~sanjeev/RHEL764bitwithtools.vhd",
+ "format": "VHD" ,
+ "ostype": "RHEL 7 (64-bit)",
+ "ispublic": "true",
+ "hypervisor": "XenServer"
+ },
+ "clusters": {
+ "clustername": "Xen Cluster Vgpu",
+ "clustertype": "CloudManaged",
+ "hypervisor": "XenServer"
+ },
+ "hosts": {
+ "nonvgpuxenserver": {
+ "hypervisor": 'XenServer',
+ "clustertype": 'CloudManaged',
+ "url": 'http://10.102.192.57',
+ "username": "root",
+ "password": "freebsd",
+ },
+ },
+ "account": {
+ "email": "test@test.com",
+ "firstname": "Test",
+ "lastname": "User",
+ "username": "test",
+ # Random characters are appended in create account to
+ # ensure unique username generated each time
+ "password": "password",
+ },
+ "service_offerings":
+ {
+ "GRID K260Q":
+ {
+ "name": "vGPU260Q",
+ "displaytext": "vGPU260Q",
+ "cpunumber": 2,
+ "cpuspeed": 1600, # in MHz
+ "memory": 3072, # In MBs
+ },
+ "GRID K240Q":
+ {
+ "name": "vGPU240Q",
+ "displaytext": "vGPU240Q",
+ "cpunumber": 2,
+ "cpuspeed": 1600, # in MHz
+ "memory": 3072, # In MBs
+ },
+ "GRID K220Q":
+ {
+ "name": "vGPU220Q",
+ "displaytext": "vGPU220Q",
+ "cpunumber": 2,
+ "cpuspeed": 1600, # in MHz
+ "memory": 3072, # In MBs
+ },
+ "GRID K200":
+ {
+ "name": "vGPU200",
+ "displaytext": "vGPU200",
+ "cpunumber": 2,
+ "cpuspeed": 1600, # in MHz
+ "memory": 3072, # In MBs
+ },
+ "passthrough":
+ {
+ "name": "vGPU passthrough",
+ "displaytext": "vGPU passthrough",
+ "cpunumber": 2,
+ "cpuspeed": 1600, # in MHz
+ "memory": 3072, # In MBs
+ },
+ "GRID K140Q":
+ {
+ # Small service offering ID to for change VM
+ # service offering from medium to small
+ "name": "vGPU140Q",
+ "displaytext": "vGPU140Q",
+ "cpunumber": 2,
+ "cpuspeed": 1600,
+ "memory": 3072,
+ },
+ "GRID K120Q":
+ {
+ "name": "vGPU120Q",
+ "displaytext": "vGPU120Q",
+ "cpunumber": 2,
+ "cpuspeed": 1600,
+ "memory": 3072,
+ },
+ "GRID K100":
+ {
+ "name": "vGPU100",
+ "displaytext": "vGPU100",
+ "cpunumber": 2,
+ "cpuspeed": 1600,
+ "memory": 3072,
+ },
+ "nonvgpuoffering":
+ {
+ "name": "nonvgpuoffering",
+ "displaytext": "nonvgpuoffering",
+ "cpunumber": 2,
+ "cpuspeed": 1600,
+ "memory": 3072,
+ }
+
+ },
+ "diskdevice": ['/dev/vdc', '/dev/vdb', '/dev/hdb', '/dev/hdc', '/dev/xvdd', '/dev/cdrom', '/dev/sr0',
+ '/dev/cdrom1'],
+ # Disk device where ISO is attached to instance
+ "mount_dir": "/mnt/tmp",
+ "sleep": 180,
+ "timeout": 60,
+ "ostype": 'Windows 8 (64-bit)',
+ "nongpu_host_ip": "10.102.192.57"
+ },
+ "acl": {
+ #data for domains and accounts
+ "domain1": {
+ "name": "D1",
+ },
+ "accountD1": {
+ "email": "testD1@test.com",
+ "firstname": "testD1",
+ "lastname": "Admin",
+ "username": "testD1",
+ "password": "password",
+ "accounttype": "1",
+ },
+ "accountD1A": {
+ "email": "testD1A@test.com",
+ "firstname": "testD1A",
+ "lastname": "User",
+ "username": "testD1A",
+ "password": "password",
+ },
+ "accountD1B": {
+ "email": "testD1B@test.com",
+ "firstname": "testD1B",
+ "lastname": "User",
+ "username": "testD1B",
+ "password": "password",
+ },
+ "domain11": {
+ "name": "D11",
+ },
+ "accountD11": {
+ "email": "testD11@test.com",
+ "firstname": "testD11",
+ "lastname": "Admin",
+ "username": "testD11",
+ "password": "password",
+ "accounttype": "1",
+ },
+ "accountD11A": {
+ "email": "testD11A@test.com",
+ "firstname": "testD11A",
+ "lastname": "User",
+ "username": "testD11A",
+ "password": "password",
+ },
+ "accountD11B": {
+ "email": "test11B@test.com",
+ "firstname": "testD11B",
+ "lastname": "User",
+ "username": "testD11B",
+ "password": "password",
+ },
+ "domain111": {
+ "name": "D111",
+ },
+ "accountD111": {
+ "email": "testD111@test.com",
+ "firstname": "testD111",
+ "lastname": "Admin",
+ "username": "testD111",
+ "password": "password",
+ },
+ "accountD111A": {
+ "email": "testD111A@test.com",
+ "firstname": "testD111A",
+ "lastname": "User",
+ "username": "testD111A",
+ "password": "password",
+ },
+ "accountD111B": {
+ "email": "testD111B@test.com",
+ "firstname": "testD111B",
+ "lastname": "User",
+ "username": "testD111B",
+ "password": "password",
+ },
+ "domain12": {
+ "name": "D12",
+ },
+ "accountD12A": {
+ "email": "testD12A@test.com",
+ "firstname": "testD12A",
+ "lastname": "User",
+ "username": "testD12A",
+ "password": "password",
+ },
+ "accountD12B": {
+ "email": "testD12B@test.com",
+ "firstname": "testD12B",
+ "lastname": "User",
+ "username": "testD12B",
+ "password": "password",
+ },
+ "domain2": {
+ "name": "D2",
+ },
+ "accountD2": {
+ "email": "testD2@test.com",
+ "firstname": "testD2",
+ "lastname": "User",
+ "username": "testD2",
+ "password": "password",
+ "accounttype": "1",
+ },
+ "accountD2A": {
+ "email": "testD2A@test.com",
+ "firstname": "testD2A",
+ "lastname": "User",
+ "username": "testD2A",
+ "password": "password",
+ },
+ "accountROOTA": {
+ "email": "testROOTA@test.com",
+ "firstname": "testROOTA",
+ "lastname": "User",
+ "username": "testROOTA",
+ "password": "password",
+ },
+
+ "accountROOT": {
+ "email": "testROOTA@test.com",
+ "firstname": "testROOT",
+ "lastname": "admin",
+ "username": "testROOT",
+ "password": "password",
+ },
+ #data reqd for virtual machine creation
+ "vmD1": {
+ "name": "d1",
+ "displayname": "d1",
+ },
+ "vmD1A": {
+ "name": "d1a",
+ "displayname": "d1a",
+ },
+ "vmD1B": {
+ "name": "d1b",
+ "displayname": "d1b",
+ },
+ "vmD11": {
+ "name": "d11",
+ "displayname": "d11",
+ },
+ "vmD11A": {
+ "name": "d11a",
+ "displayname": "d11a",
+ },
+ "vmD11B": {
+ "name": "d11b",
+ "displayname": "d11b",
+ },
+ "vmD111": {
+ "name": "d111",
+ "displayname": "d111",
+ },
+ "vmD111A": {
+ "name": "d111a",
+ "displayname": "d111a",
+ },
+ "vmD111B": {
+ "name": "d111b",
+ "displayname": "d111b",
+ },
+ "vmD12A": {
+ "name": "d12a",
+ "displayname": "d12a",
+ },
+ "vmD12B": {
+ "name": "d12b",
+ "displayname": "d12b",
+ },
+ "vmD2A": {
+ "name": "d2a",
+ "displayname": "d2a",
+ },
+
+ "vmROOTA": {
+ "name": "roota",
+ "displayname": "roota",
+ },
+ "vmROOT": {
+ "name": "root",
+ "displayname": "root",
+ },
+
+ #data reqd for Network creation
+ "network_all": {
+ "name": "SharedNetwork-All",
+ "displaytext": "SharedNetwork-All",
+ "vlan": "4001",
+ "gateway": "10.223.1.1",
+ "netmask": "255.255.255.0",
+ "startip": "10.223.1.2",
+ "endip": "10.223.1.100",
+ "acltype": "Domain"
+ },
+ "network_domain_with_no_subdomain_access": {
+ "name": "SharedNetwork-Domain-nosubdomain",
+ "displaytext": "SharedNetwork-Domain-nosubdomain",
+ "vlan": "4002",
+ "gateway": "10.223.1.1",
+ "netmask": "255.255.255.0",
+ "startip": "10.223.1.2",
+ "endip": "10.223.1.100",
+ "acltype": "Domain",
+ "subdomainaccess": "false"
+ },
+ "network_domain_with_subdomain_access": {
+ "name": "SharedNetwork-Domain-withsubdomain",
+ "displaytext": "SharedNetwork-Domain-withsubdomain",
+ "vlan": "4003",
+ "gateway": "10.223.1.1",
+ "netmask": "255.255.255.0",
+ "startip": "10.223.1.2",
+ "endip": "10.223.1.100",
+ "acltype": "Domain",
+ "subdomainaccess": "true"
+ },
+ "network_account": {
+ "name": "SharedNetwork-Account",
+ "displaytext": "SharedNetwork-Account",
+ "vlan": "4004",
+ "gateway": "10.223.1.1",
+ "netmask": "255.255.255.0",
+ "startip": "10.223.1.2",
+ "endip": "10.223.1.100",
+ "acltype": "Account"
+ },
+
+ "network": {
+ "name": "Network-",
+ "displaytext": "Network-",
+ "gateway": "10.223.1.1",
+ "netmask": "255.255.255.0",
+ "startip": "10.223.59.200",
+ "endip": "10.223.59.240",
+ "vlan": "1000"
+ },
+ "netscaler": {
+ "ipaddress": "",
+ "username": "",
+ "password": "",
+ "networkdevicetype": "",
+ "publicinterface": "",
+ "privateinterface": "",
+ "numretries": "",
+ "lbdevicededicated": "False",
+ "lbdevicecapacity": 2,
+ "port": 22
+ },
+ "iscsi": {
+ "url": "",
+ "name": "Primary iSCSI"
+ },
+ "host": {
+ "publicport": 22,
+ "username": "root",
+ "password": "password",
+ },
+ "ldap_account": {
+ "email": "",
+ "firstname": "",
+ "lastname": "",
+ "username": "",
+ "password": "",
+ },
+ "ldap_configuration": {
+ "basedn": "",
+ "emailAttribute": "",
+ "userObject": "",
+ "usernameAttribute": "",
+ "hostname": "",
+ "port": "",
+ "ldapUsername": "",
+ "ldapPassword": ""
+ },
+ "systemVmDelay": 120,
+ "setUsageConfigurationThroughTestCase": False,
+ "vmware_cluster" : {
+ "hypervisor": 'VMware',
+ "clustertype": 'ExternalManaged',
+ "username": '',
+ "password": '',
+ "url": '',
+ "clustername": 'VMWare Cluster with Space in DC name',
+ "startip": "10.223.1.2",
+ "endip": "10.223.1.100",
+ },
+ #small service offering
+ "service_offering": {
+ "small": {
+ "name": "Small Instance",
+ "displaytext": "Small Instance",
+ "cpunumber": 1,
+ "cpuspeed": 100,
+ "memory": 128,
+ },
+ },
+ "ostype": 'CentOS 5.6 (64-bit)',
+ },
+ "test_34_DeployVM_in_SecondSGNetwork": {
+ "zone": "advsg",
+ "config": "D:\ACS-Repo\setup\dev\\advancedsg.cfg", #Absolute path to cfg file
+ #For sample configuration please refer to <ACS repo>/setup/dev/advancedsg.cfg
+ "template": "CentOS 5.3(64-bit) no GUI (Simulator)",
+ "dbSvr": {
+ "dbSvr": "10.146.0.133",
+ "passwd": "cloud",
+ "db": "cloud",
+ "port": 3306,
+ "user": "cloud"
+ },
+ "mgtSvr": [
+ {
+ "mgtSvrIp": "10.146.0.133",
+ "passwd": "password",
+ "user": "root",
+ "port": 8096
+ }
+ ],
+ "ipranges": [
+ {
+ "startip": "10.147.32.150",
+ "endip": "10.147.32.153",
+ "netmask": "255.255.255.0",
+ "vlan": "32",
+ "gateway": "10.147.32.1"
+ }
+ ]
+ },
+
+ "interop":
+ {
+ "VHD":
+ {
+ "displaytext": "Windows 8 (64-bit)",
+ "name": "win8withpvxen",
+ "passwordenabled": False,
+ "url": "http://people.apache.org/~sanjeev/79211594-1d4a-4dee-ae6c-c5c315ded2be.vhd",
+ "format": "VHD" ,
+ "ostype": "Windows 8 (64-bit)",
+ "ispublic": "true",
+ "hypervisor": "XenServer"
+
+ },
+ "OVA":
+ {
+ "displaytext": "Windows 8 (64-bit)",
+ "name": "win8withpvvmware",
+ "passwordenabled": False,
+ "url": "http://pleaseupdateURL/",
+ "format": "OVA" ,
+ "ostype": "Windows 8 (64-bit)",
+ "ispublic": "true",
+ "hypervisor": "VMware"
+ },
+ "template": {
+ "displaytext": "windowsxdtemplate",
+ "name": "windowsxdtemplate",
+ "passwordenabled": False,
+ "ostype": "Windows 8 (64-bit)"
+ },
+ },
+
+ "browser_upload_volume":{
+ "VHD": {
+ "diskname": "XenUploadVol",
+ "url": "http://people.apache.org/~sanjeev/rajani-thin-volume.vhd",
+ "checksum": "09b08b6abb1b903fca7711d3ac8d6598",
+ },
+ "OVA": {
+ "diskname": "VMwareUploadVol",
+ "url": "http://people.apache.org/~sanjeev/CentOS5.5(64bit)-vmware-autoscale.ova",
+ "checksum": "da997b697feaa2f1f6e0d4785b0cece2",
+ },
+ "QCOW2": {
+ "diskname": "KVMUploadVol",
+ "url": "http://people.apache.org/~sanjeev/rajani-thin-volume.qcow2",
+ "checksum": "02de0576dd3a61ab59c03fd795fc86ac",
+ },
+ 'browser_resized_disk_offering': {
+ "displaytext": "Resizeddisk",
+ "name": "Resizeddisk",
+ "disksize": 3,
+ }
+ },
+ "browser_upload_template": {
+ "VHD": {
+ "templatename": "XenUploadtemplate",
+ "displaytext": "XenUploadtemplate",
+ "url": "http://people.apache.org/~sanjeev/centos56-x86_64.vhd.bz2",
+ "hypervisor":"XenServer",
+ "checksum": "09b08b6abb1b903fca7711d3ac8d6598",
+ "ostypeid":"74affaea-c658-11e4-ad38-a6d1374244b4"
+ },
+ "OVA": {
+ "templatename": "VMwareUploadtemplate",
+ "displaytext": "VMwareUploadtemplate",
+ "url": "http://people.apache.org/~sanjeev/CentOS5.3-x86_64.ova",
+ "checksum": "02de0576dd3a61ab59c03fd795fc86ac",
+ "hypervisor":"VMware",
+ "ostypeid":"74affaea-c658-11e4-ad38-a6d1374244b4"
+ },
+ "QCOW2": {
+ "templatename": "KVMUploadtemplate",
+ "displaytext": "VMwareUploadtemplate",
+ "url": "http://people.apache.org/~sanjeev/eec2209b-9875-3c8d-92be-c001bd8a0faf.qcow2.bz2",
+ "checksum": "da997b697feaa2f1f6e0d4785b0cece2",
+ "hypervisor":"KVM",
+ "ostypeid":"2e02e376-cdf3-11e4-beb3-8aa6272b57ef"
+ },
+ },
+ "configurableData":
+ {
+ "portableIpRange": {
+ "gateway": "10.223.59.1",
+ "netmask": "255.255.255.0",
+ "startip": "10.223.59.200",
+ "endip": "10.223.59.240",
+ "vlan": "1000"
+ },
+ "netscaler": {
+ "ipaddress": "",
+ "username": "",
+ "password": "",
+ "networkdevicetype": "",
+ "publicinterface": "",
+ "privateinterface": "",
+ "numretries": "",
+ "lbdevicededicated": "False",
+ "lbdevicecapacity": 2,
+ "port": 22
+ },
+ "iscsi": {
+ "url": "",
+ "name": "Primary iSCSI"
+ },
+ "host": {
+ "publicport": 22,
+ "username": "root",
+ "password": "password",
+ },
+ "ldap_account": {
+ "email": "",
+ "firstname": "",
+ "lastname": "",
+ "username": "",
+ "password": "",
+ },
+ "link_ldap_details": {
+ "domain_name": "",
+ "accounttype": "",
+ "name": "",
+ "type": "",
+ "admin": "",
+ "linkLdapUsername": "",
+ "linkLdapPassword": "",
+ "linkLdapNestedUser": "",
+ "linkLdapNestedPassword": ""
+
+ },
+ "ldap_configuration": {
+ "basedn": "",
+ "emailAttribute": "",
+ "userObject": "",
+ "usernameAttribute": "",
+ "hostname": "",
+ "port": "",
+ "ldapUsername": "",
+ "ldapPassword": ""
+ },
+ "systemVmDelay": 120,
+ "setUsageConfigurationThroughTestCase": True,
+ "vmware_cluster": {
+ "hypervisor": 'VMware',
+ "clustertype": 'ExternalManaged',
+ "username": '',
+ "password": '',
+ "url": '',
+ "clustername": 'VMWare Cluster with Space in DC name',
+ },
+ "upload_volume": {
+ "diskname": "UploadVol",
+ "format": "VHD",
+ "url": "http://download.cloudstack.org/releases/2.0.0/UbuntuServer-10-04-64bit.vhd.bz2",
+ "checksum": "",
+ },
+ "bootableIso":
+ {
+ "displaytext": "Test Bootable ISO",
+ "name": "testISO",
+ "bootable": True,
+ "ispublic": False,
+ "url": "http://people.apache.org/~sanjeev/CentOS-6.3-x86_64-bin-DVD1.iso",
+ "ostype": 'CentOS 6.3 (64-bit)',
+ "mode": 'HTTP_DOWNLOAD'
+ },
+ "setHostConfigurationForIngressRule": False,
+ "restartManagementServerThroughTestCase": False,
+ "vmxnet3template": {
+ "displaytext": "VMXNET3 Template",
+ "name": "VMXNET3 template",
+ "ostype": "CentOS 5.6 (64-bit)",
+ "isfeatured": True,
+ "ispublic": False,
+ "isextractable": True,
+ "mode": "HTTP_DOWNLOAD",
+ "templatefilter": "self",
+ "url": "http://people.apache.org/~sanjeev/systemvm64template-2014-09-30-4.3-vmware.ova",
+ "hypervisor": "vmware",
+ "format": "OVA",
+ "nicadapter": "vmxnet3",
+ "kvm": {
+ "url": ""
+ },
+ "vmware": {
+ "url": ""
+ },
+ "xenserver": {
+ "url": ""
+ },
+ "hyperv": {
+ "url": ""
+ },
+ "ostype": 'CentOS 5.3 (64-bit)',
+ "mode": 'HTTP_DOWNLOAD'
+ }
+ },
+ # Nuage VSP SDN plugin specific test data
+ "nuagevsp": {
+ # Services supported by the Nuage VSP plugin for Isolated networks
+ "isolated_network_offering": {
+ "name": 'nuage_marvin',
+ "displaytext": 'nuage_marvin',
+ "guestiptype": 'Isolated',
+ "supportedservices": 'Dhcp,SourceNat,Connectivity,StaticNat,UserData,Firewall,Dns',
+ "traffictype": 'GUEST',
+ "availability": 'Optional',
+ "serviceProviderList": {
+ "Dhcp": 'NuageVsp',
+ "StaticNat": 'NuageVsp',
+ "SourceNat": 'NuageVsp',
+ "Firewall": 'NuageVsp',
+ "Connectivity": 'NuageVsp',
+ "UserData": 'VirtualRouter',
+ "Dns": 'VirtualRouter'
+ },
+ "serviceCapabilityList": {
+ "SourceNat": {"SupportedSourceNatTypes": "perzone"}
+ }
+ },
+ # Services supported by the Nuage VSP plugin for VPC networks
+ "vpc_network_offering": {
+ "name": 'nuage_vpc_marvin',
+ "displaytext": 'nuage_vpc_marvin',
+ "guestiptype": 'Isolated',
+ "supportedservices": 'Dhcp,StaticNat,SourceNat,NetworkACL,Connectivity,UserData,Dns',
+ "traffictype": 'GUEST',
+ "availability": 'Optional',
+ "useVpc": 'on',
+ "ispersistent": 'True',
+ "serviceProviderList": {
+ "Dhcp": "NuageVsp",
+ "StaticNat": "NuageVsp",
+ "SourceNat": "NuageVsp",
+ "NetworkACL": "NuageVsp",
+ "Connectivity": "NuageVsp",
+ "UserData": "VpcVirtualRouter",
+ "Dns": "VpcVirtualRouter"
+ },
+ "serviceCapabilityList": {
+ "SourceNat": {"SupportedSourceNatTypes": "perzone"}
+ }
+ },
+ "vpc_network_offering_internal_lb": {
+ "name": "nuage_vpc_marvin_internal_lb",
+ "displaytext": "nuage_vpc_marvin_internal_lb",
+ "guestiptype": 'Isolated',
+ "supportedservices": 'Dhcp,Lb,StaticNat,SourceNat,NetworkACL,Connectivity,UserData,Dns',
+ "traffictype": 'GUEST',
+ "availability": 'Optional',
+ "useVpc": 'on',
+ "ispersistent": 'True',
+ "serviceProviderList": {
+ "Dhcp": "NuageVsp",
+ "Lb": "InternalLbVm",
+ "StaticNat": "NuageVsp",
+ "SourceNat": "NuageVsp",
+ "NetworkACL": "NuageVsp",
+ "Connectivity": "NuageVsp",
+ "UserData": "VpcVirtualRouter",
+ "Dns": "VpcVirtualRouter"
+ },
+ "serviceCapabilityList": {
+ "SourceNat": {"SupportedSourceNatTypes": "perzone"},
+ "Lb": {"lbSchemes": "internal", "SupportedLbIsolation": "dedicated"}
+ }
+ },
+ # Services supported by the Nuage VSP plugin for VPCs
+ "vpc_offering": {
+ "name": 'Nuage VSP VPC offering',
+ "displaytext": 'Nuage VSP VPC offering',
+ "supportedservices": 'Dhcp,StaticNat,SourceNat,NetworkACL,Connectivity,UserData,Dns',
+ "serviceProviderList": {
+ "Dhcp": "NuageVsp",
+ "StaticNat": "NuageVsp",
+ "SourceNat": "NuageVsp",
+ "NetworkACL": "NuageVsp",
+ "Connectivity": "NuageVsp",
+ "UserData": "VpcVirtualRouter",
+ "Dns": "VpcVirtualRouter"
+ }
+ },
+ "vpc_offering_lb": {
+ "name": 'Nuage VSP VPC offering with Lb',
+ "displaytext": 'Nuage VSP VPC offering with Lb',
+ "supportedservices": 'Dhcp,Lb,StaticNat,SourceNat,NetworkACL,Connectivity,UserData,Dns',
+ "serviceProviderList": {
+ "Dhcp": "NuageVsp",
+ "Lb": "InternalLbVm",
+ "StaticNat": "NuageVsp",
+ "SourceNat": "NuageVsp",
+ "NetworkACL": "NuageVsp",
+ "Connectivity": "NuageVsp",
+ "UserData": "VpcVirtualRouter",
+ "Dns": "VpcVirtualRouter"
+ }
+ },
+ "shared_nuage_network_offering": {
+ "name": 'nuage_marvin',
+ "displaytext": 'nuage_marvin',
+ "guestiptype": 'shared',
+ "supportedservices": 'Dhcp,Connectivity',
+ "traffictype": 'GUEST',
+ "specifyVlan": "False",
+ "specifyIpRanges": "True",
+ "availability": 'Optional',
+ "serviceProviderList": {
+ "Dhcp": "NuageVsp",
+ "Connectivity": "NuageVsp"
+ }
+ },
+ "shared_nuage_public_network_offering": {
+ "name": 'nuage_marvin',
+ "displaytext": 'nuage_marvin',
+ "guestiptype": 'shared',
+ "supportedservices": 'Dhcp,Connectivity',
+ "traffictype": 'GUEST',
+ "specifyVlan": "False",
+ "specifyIpRanges": "True",
+ "availability": 'Optional',
+ "serviceProviderList": {
+ "Dhcp": "NuageVsp",
+ "Connectivity": "NuageVsp"
+ },
+ "serviceCapabilityList": {
+ "Connectivity": {
+ "PublicAccess": "true"
+ }
+ }
+
+ },
+ # Test data for Shared Network creation
+ "network_all": {
+ "name": "SharedNetwork-All-nuage",
+ "displaytext": "SharedNetwork-All-nuage",
+ "gateway": "10.223.1.1",
+ "netmask": "255.255.255.0",
+ "startip": "10.223.1.21",
+ "endip": "10.223.1.100",
+ "acltype": "Domain"
+ },
+ "network_domain_with_no_subdomain_access": {
+ "name": "SharedNetwork-Domain-nosubdomain-nuage",
+ "displaytext": "SharedNetwork-Domain-nosubdomain-nuage",
+ "gateway": "10.222.1.1",
+ "netmask": "255.255.255.0",
+ "startip": "10.222.1.2",
+ "endip": "10.222.1.100",
+ "acltype": "Domain",
+ "subdomainaccess": "false"
+ },
+ "network_domain_with_subdomain_access": {
+ "name": "SharedNetwork-Domain-withsubdomain-nuage",
+ "displaytext": "SharedNetwork-Domain-withsubdomain-nuage",
+ "gateway": "10.221.1.1",
+ "netmask": "255.255.255.0",
+ "startip": "10.221.1.2",
+ "endip": "10.221.1.100",
+ "acltype": "Domain",
+ "subdomainaccess": "true"
+ },
+ "network_account": {
+ "name": "SharedNetwork-Account-nuage",
+ "displaytext": "SharedNetwork-Account-nuage",
+ "gateway": "10.220.1.1",
+ "netmask": "255.255.255.0",
+ "startip": "10.220.1.2",
+ "endip": "10.220.1.100",
+ "acltype": "Account"
+ },
+ "publiciprange1": {
+ "gateway": "10.223.1.1",
+ "netmask": "255.255.255.0",
+ "startip": "10.223.1.101",
+ "endip": "10.223.1.105",
+ "forvirtualnetwork": "false"
+ },
+ "publiciprange2": {
+ "gateway": "10.219.1.1",
+ "netmask": "255.255.255.0",
+ "startip": "10.219.1.2",
+ "endip": "10.219.1.5",
+ "forvirtualnetwork": "false"
+ },
+ "publiciprange3": {
+ "gateway": "10.223.1.1",
+ "netmask": "255.255.255.0",
+ "startip": "10.223.1.2",
+ "endip": "10.223.1.20",
+ "forvirtualnetwork": "false"
+ }
+ }
+}
diff --git a/test/integration/plugins/nuagevsp/nuage_vsp_statistics.py b/test/integration/plugins/nuagevsp/nuage_vsp_statistics.py
new file mode 100644
index 00000000000..f4fcde84dba
--- /dev/null
+++ b/test/integration/plugins/nuagevsp/nuage_vsp_statistics.py
@@ -0,0 +1,202 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import jpype
+from jpype import *
+from jpype import java
+from jpype import javax
+
+J_STRING = "java.lang.String"
+
+
+class VsdDataCollector:
+ def __init__(self, name, host="localhost", port=1099, debug=False,
+ output_channel=None):
+ self.jmx = ConnectionJmx(host, port, debug, output_channel)
+ self.jmx.create_management_object(name=name)
+ self.saved_stats = None
+ self.saved_vsd_calls = 0
+
+ def start_test(self):
+ self.saved_stats = self.jmx.get_attribute("VsdStatisticsReport")
+ self.saved_vsd_calls = self.jmx.get_attribute("VSDStatistics")
+ return
+
+ def end_test(self):
+ self.jmx.print_rapport(old_stats=self.saved_stats,
+ old_vsd_count=self.saved_vsd_calls)
+ return
+
+
+class ConnectionJmx:
+
+ def __init__(self, host="localhost", port=1099, debug=False,
+ output_channel=None):
+ self.host = host
+ self.port = port
+ self.url = "service:jmx:rmi:///jndi/rmi://%s:%d/jmxrmi" % (host, port)
+ self.debug = debug
+ self.mbean = None
+ self.output_channel = output_channel
+ jpype.startJVM(jpype.get_default_jvm_path())
+ if debug:
+ self.__print_to_ouput_channel("JVM loaded")
+ self.__print_to_ouput_channel(jpype.get_default_jvm_path())
+
+ jmx_url = javax.management.remote.JMXServiceURL(self.url)
+ jmx_soc = javax.management.remote.JMXConnectorFactory.connect(
+ jmx_url, java.util.HashMap())
+ self.connection = jmx_soc.getMBeanServerConnection()
+ if self.debug:
+ self.__print_to_ouput_channel("Connection successful")
+
+ def __print_to_ouput_channel(self, text):
+ if self.output_channel:
+ self.output_channel.debug(text)
+ else:
+ print text
+
+ def create_management_object(self, domain="com.cloud",
+ type="NuageVspResource",
+ name="Nuage VSD - 0.0.0.0"):
+ if name is not None:
+ object_name = domain + ":type=" + type + ", name=" + name
+ else:
+ object_name = domain + ":" + type
+
+ if self.debug:
+ self.__print_to_ouput_channel(object_name)
+
+ self.mbean = javax.management.ObjectName(object_name)
+ return self.mbean
+
+ def get_vsd_statistics_by_request_and_entity_type(self,
+ entity_type,
+ request_type,
+ mbean=None):
+ self._get_stats_by_entity_or_request_type(
+ mbean, [[entity_type, request_type]],
+ "getVsdStatisticsByEntityType")
+
+ def _jStringArray(self, elements):
+ return jpype.JArray(java.lang.String)(elements)
+
+ def get_vsd_statistics_by_request_type(self, request_type, mbean=None):
+ return self._get_stats_by_entity_or_request_type(
+ mbean, [request_type], "getVsdStatisticsByRequestType")
+
+ def get_vsd_statistics_by_entity_type(self, entity_type, mbean=None):
+ return self._get_stats_by_entity_or_request_type(
+ mbean, [entity_type], "getVsdStatisticsByEntityType")
+
+ def _get_stats_by_entity_or_request_type(self, vars, method, mbean=None):
+ if not mbean:
+ mbean = self.mbean
+ jarray = self._jStringArray(vars)
+ signature = self._jStringArray([J_STRING for _ in vars])
+ result = self.connection.invoke(mbean, method, jarray, signature)
+ if self.debug:
+ self.__print_to_ouput_channel(vars + ": " + str(result))
+ return result
+
+ def get_attribute(self, attribute, mbean=None):
+ if not mbean:
+ mbean = self.mbean
+
+ result = self.connection.getAttribute(mbean, attribute)
+ if self.debug:
+ self.__print_to_ouput_channel("Attribute " + attribute + ": " +
+ str(result))
+ return result
+
+ def print_rapport(self, mbean=None, old_stats=None, old_vsd_count=0):
+ if not mbean:
+ mbean = self.mbean
+ stat = self.get_attribute("VsdStatisticsReport", mbean)
+ number_of_vsd_calls = int(str(self.get_attribute("VSDStatistics",
+ mbean)))
+ number_of_vsd_calls = number_of_vsd_calls - int(str(old_vsd_count))
+
+ self.__print_to_ouput_channel("\n================"
+ "RAPPORT:"
+ "================\n")
+ self.__print_to_ouput_channel("Total VSD calls: " +
+ str(number_of_vsd_calls))
+ self.__print_to_ouput_channel("For each Entity:\n")
+ self.__print_total_for_entity(stat, old_stats)
+ self.__print_to_ouput_channel("\nFor each Request:\n")
+ self.__print_total_per_request(stat, old_stats)
+ self.__print_to_ouput_channel("\nCombined:\n")
+ self.__print_total_per_entity_and_request(stat, old_stats)
+ self.__print_to_ouput_channel("\n============="
+ "END OF RAPPORT"
+ "=============")
+
+ def __print_total_per_request(self, stat, old_stat=None):
+ data = dict()
+
+ entries = ((entry.getKey(), entry.getValue().get())
+ for requestmap in stat.values()
+ for entry in requestmap.entrySet())
+
+ for request, value in entries:
+ if request in data:
+ data[request] += value
+ else:
+ data[request] = value
+
+ if old_stat:
+ old_entries = ((entry.getKey(), entry.getValue().get())
+ for requestmap in old_stat.values()
+ for entry in requestmap.entrySet())
+
+ for request, value in old_entries:
+ if request in data:
+ data[request] -= value
+ else:
+ data[request] = 0
+
+ for key, value in data.iteritems():
+ self.__print_to_ouput_channel(" " + str(key) + ": " + str(value))
+
+ def __print_total_per_entity_and_request(self, stat, old_stat=None):
+ for entity in stat:
+ self.__print_to_ouput_channel(entity + ":")
+ for request in stat[entity]:
+ previous = 0
+ if old_stat and old_stat[entity] and old_stat[entity][request]:
+ previous = int(str(old_stat[entity][request]))
+
+ current = int(str(stat[entity][request]))
+
+ self.__print_to_ouput_channel(" " + str(request) + ":" +
+ str(current - previous))
+ self.__print_to_ouput_channel("--------------------"
+ "--------------------")
+
+ def __print_total_for_entity(self, stat, old_stat=None):
+ for entity in stat:
+ total = 0
+ for val in stat[entity]:
+ minus = 0
+ if old_stat and old_stat[entity] and old_stat[entity][val]:
+ minus = int(str(old_stat[entity][val]))
+ total = str(stat[entity][val])
+
+ total = int(total) - minus
+ self.__print_to_ouput_channel(" " + str(entity) +
+ ": " + str(total))
diff --git a/test/integration/plugins/nuagevsp/test_nuage_static_nat.py b/test/integration/plugins/nuagevsp/test_nuage_static_nat.py
index 9e6cdde4dc9..9d168e93d0f 100644
--- a/test/integration/plugins/nuagevsp/test_nuage_static_nat.py
+++ b/test/integration/plugins/nuagevsp/test_nuage_static_nat.py
@@ -26,8 +26,11 @@
from marvin.cloudstackAPI import (enableNuageUnderlayVlanIpRange,
disableNuageUnderlayVlanIpRange,
listNuageUnderlayVlanIpRanges)
+from marvin.lib.common import list_virtual_machines
+
# Import System Modules
from nose.plugins.attrib import attr
+import threading
import copy
import time
@@ -150,7 +153,7 @@ def verify_StaticNAT_traffic(self, network, public_ip, vpc=None,
# wget from VM
tries = 0
- max_tries = 3 if non_default_nic else 10
+ max_tries = 3 if non_default_nic else 120
filename = None
headers = None
while tries < max_tries:
@@ -162,30 +165,31 @@ def verify_StaticNAT_traffic(self, network, public_ip, vpc=None,
except Exception as e:
self.debug("Failed to wget from VM - %s" % e)
self.debug("Retrying wget from VM after some time...")
- time.sleep(60)
+ time.sleep(5)
tries += 1
- if not filename and not headers:
- if non_default_nic:
- self.debug("Failed to wget from VM via this NIC as it is not "
- "the default NIC")
- else:
- self.fail("Failed to wget from VM")
-
- # Removing Ingress Firewall/Network ACL rule
- self.debug("Removing the created Ingress Firewall/Network ACL "
- "rule in the network...")
- public_http_rule.delete(self.api_client)
+ try:
+ if not filename and not headers:
+ if non_default_nic:
+ self.debug("Failed to wget from VM via this NIC as it "
+ "is not the default NIC")
+ else:
+ self.fail("Failed to wget from VM")
+ finally:
+ # Removing Ingress Firewall/Network ACL rule
+ self.debug("Removing the created Ingress Firewall/Network ACL "
+ "rule in the network...")
+ public_http_rule.delete(self.api_client)
- # VSD verification
- with self.assertRaises(Exception):
- self.verify_vsd_firewall_rule(public_http_rule)
- self.debug("Ingress Firewall/Network ACL rule successfully "
- "deleted in VSD")
+ # VSD verification
+ with self.assertRaises(Exception):
+ self.verify_vsd_firewall_rule(public_http_rule)
+ self.debug("Ingress Firewall/Network ACL rule successfully "
+ "deleted in VSD")
- self.debug("Successfully verified Static NAT traffic by performing "
- "wget traffic test with the given Static NAT enabled "
- "public IP - %s" % public_ip)
+ self.debug("Successfully verified Static NAT traffic by "
+ "performing wget traffic test with the given Static "
+ "NAT enabled public IP - %s" % public_ip)
# wget_from_internet - From within the given VM (ssh client),
# fetches index.html file of an Internet web server, wget www.google.com
@@ -240,30 +244,31 @@ def verify_StaticNAT_Internet_traffic(self, vm, network, public_ip,
# SSH into VM
ssh_client = None
- if non_default_nic:
- with self.assertRaises(Exception):
- self.ssh_into_VM(vm, public_ip, negative_test=True)
- self.debug("Can not SSH into the VM via this NIC as it is not the "
- "default NIC")
- else:
- ssh_client = self.ssh_into_VM(vm, public_ip)
-
- # wget from Internet
- test_result = None
- if ssh_client and self.isInternetConnectivityAvailable:
- timeout = 100 if negative_test else 300
- test_result = self.wget_from_Internet(ssh_client, timeout)
-
- # Removing Ingress Firewall/Network ACL rule
- self.debug("Removing the created Ingress Firewall/Network ACL "
- "rule in the network...")
- public_ssh_rule.delete(self.api_client)
+ try:
+ if non_default_nic:
+ with self.assertRaises(Exception):
+ self.ssh_into_VM(vm, public_ip, negative_test=True)
+ self.debug("Can not SSH into the VM via this NIC as it is "
+ "not the default NIC")
+ else:
+ ssh_client = self.ssh_into_VM(vm, public_ip)
+
+ # wget from Internet
+ test_result = None
+ if ssh_client and self.isInternetConnectivityAvailable:
+ timeout = 100 if negative_test else 300
+ test_result = self.wget_from_Internet(ssh_client, timeout)
+ finally:
+ # Removing Ingress Firewall/Network ACL rule
+ self.debug("Removing the created Ingress Firewall/Network ACL "
+ "rule in the network...")
+ public_ssh_rule.delete(self.api_client)
- # VSD verification
- with self.assertRaises(Exception):
- self.verify_vsd_firewall_rule(public_ssh_rule)
- self.debug("Ingress Firewall/Network ACL rule successfully "
- "deleted in VSD")
+ # VSD verification
+ with self.assertRaises(Exception):
+ self.verify_vsd_firewall_rule(public_ssh_rule)
+ self.debug("Ingress Firewall/Network ACL rule successfully "
+ "deleted in VSD")
# Removing Egress Network ACL rule
if vpc and self.http_proxy:
@@ -293,6 +298,17 @@ def verify_StaticNAT_Internet_traffic(self, vm, network, public_ip,
"(wget www.google.com) test from VM as there is no "
"Internet connectivity in the data center")
+ # enable_staticNat_on_a_starting_vm - Enables Static Nat on a starting VM
+ # in the given network with the given public IP.
+ def enable_staticNat_on_a_starting_vm(self):
+ self.debug("Enables Static Nat on a starting VM in the network - %s "
+ "with the given public IP - %s" %
+ (self.network, self.public_ip))
+ time.sleep(15)
+ vm_list = list_virtual_machines(self.api_client, listall=True)
+ self.create_StaticNatRule_For_VM(
+ vm_list[0], self.public_ip, self.network)
+
@attr(tags=["advanced", "nuagevsp"], required_hardware="false")
def test_01_nuage_StaticNAT_public_ip_range(self):
"""Test Nuage VSP Public IP Range creation and deletion
@@ -1579,7 +1595,7 @@ def test_08_nuage_StaticNAT_vm_nic_operations_traffic(self):
self.verify_vsd_floating_ip(network_2, vm, public_ip_2.ipaddress)
# Verifying Static NAT traffic
- with self.assertRaises(Exception):
+ with self.assertRaises(AssertionError):
self.verify_StaticNAT_traffic(network_1, public_ip_1)
self.debug("Static NAT rule not enabled in this VM NIC")
self.verify_StaticNAT_traffic(network_2, public_ip_2)
@@ -2086,3 +2102,74 @@ def test_10_nuage_StaticNAT_network_restarts_traffic(self):
# from the deployed VM
self.verify_StaticNAT_Internet_traffic(
vpc_vm, vpc_tier, public_ip_2, vpc=vpc)
+
+ # Bug CLOUDSTACK-9751
+ @attr(tags=["advanced", "nuagevsp"], required_hardware="true")
+ def test_11_nuage_enable_staticNat_when_vr_is_in_starting_state(self):
+ """Test Nuage VSP Static NAT functionality by enabling Static Nat when
+ VR is in starting state
+ """
+
+ # 1. Create a Nuage VSP Isolated network offering.
+ # 2. Create an Isolated network with above created offering.
+ # 3. Deploy a VM in the above created Isolated network,
+ # which starts a VR.
+ # 4. While VR is in the starting state, acquire a public IP and enable
+ # static nat in another thread.
+ # 5. Verify that Static NAT is successfully enabled in both CloudStack
+ # and VSD.
+ # 6. Delete all the created objects (cleanup).
+
+ # Creating network offering
+ self.debug("Creating Nuage VSP Isolated Network offering with Static "
+ "NAT service provider as NuageVsp...")
+ net_off = self.create_NetworkOffering(
+ self.test_data["nuagevsp"]["isolated_network_offering"])
+ self.validate_NetworkOffering(net_off, state="Enabled")
+
+ # Creating an Isolated network
+ self.debug("Creating an Isolated network with Static NAT service...")
+ self.network = self.create_Network(net_off, gateway='10.1.1.1')
+ self.validate_Network(self.network, state="Allocated")
+
+ # Acquiring a Public IP
+ self.debug("Acquiring a Public IP in the created Isolated network...")
+ self.public_ip = self.acquire_PublicIPAddress(self.network)
+ self.validate_PublicIPAddress(self.public_ip, self.network)
+
+ # Enabling Static NAT on a starting VM
+ self.debug("Creating a thread for enabling Static Nat on a starting "
+ "VM...")
+ static_nat_thread = threading.Thread(
+ name='enable_static_nat',
+ target=self.enable_staticNat_on_a_starting_vm)
+ static_nat_thread.start()
+
+ vm = self.create_VM(self.network)
+
+ # Check the status of Static Nat thread and if it is not finished then
+ # below command will wait for it to finish
+ self.debug("Waiting for for enabling Static Nat on a starting VM "
+ "thread to finish...")
+ static_nat_thread.join()
+
+ # CloudStack verification for the implemented Isolated Network
+ self.validate_Network(self.network, state="Implemented")
+ vr = self.get_Router(self.network)
+ self.check_Router_state(vr, state="Running")
+ self.check_VM_state(vm, state="Running")
+
+ # VSD verification for the implemented Isolated Network
+ self.verify_vsd_network(self.domain.id, self.network)
+ self.verify_vsd_router(vr)
+ self.verify_vsd_vm(vm)
+
+ # CloudStack verification for Static NAT functionality
+ self.validate_PublicIPAddress(
+ self.public_ip, self.network, static_nat=True, vm=vm)
+
+ # VSD verification for Static NAT functionality
+ self.verify_vsd_floating_ip(self.network, vm, self.public_ip.ipaddress)
+
+ # Verifying Static NAT traffic
+ self.verify_StaticNAT_traffic(self.network, self.public_ip)
diff --git a/test/integration/plugins/nuagevsp/test_nuage_vpc_internal_lb.py b/test/integration/plugins/nuagevsp/test_nuage_vpc_internal_lb.py
index 97319aa2b1f..8a2ea4f179e 100644
--- a/test/integration/plugins/nuagevsp/test_nuage_vpc_internal_lb.py
+++ b/test/integration/plugins/nuagevsp/test_nuage_vpc_internal_lb.py
@@ -1428,6 +1428,7 @@ def test_05_nuage_internallb_traffic(self):
http_rule["publicport"])
# Verifying Internal LB (wget) traffic tests
+ # Bug CLOUDSTACK-9749
self.verify_lb_wget_file(
wget_file_1, [internal_vm_1, internal_vm_1_1, internal_vm_1_2])
self.verify_lb_wget_file(
@@ -1908,9 +1909,17 @@ def test_07_nuage_internallb_vpc_network_restarts_traffic(self):
# Internal LB (wget) traffic test
ssh_client = self.ssh_into_VM(public_vm, public_ip)
- wget_file = self.wget_from_vm_cmd(
- ssh_client, int_lb_rule_1.sourceipaddress,
- self.test_data["http_rule"]["publicport"])
+ tries = 0
+ while tries < 120:
+ wget_file = self.wget_from_vm_cmd(
+ ssh_client, int_lb_rule_1.sourceipaddress,
+ self.test_data["http_rule"]["publicport"])
+ if wget_file != "":
+ break
+ self.debug("Waiting for the InternalLbVm in the Internal tier to "
+ "be fully resolved for (wget) traffic test...")
+ time.sleep(5)
+ tries += 1
# Verifying Internal LB (wget) traffic test
self.verify_lb_wget_file(
@@ -1954,9 +1963,17 @@ def test_07_nuage_internallb_vpc_network_restarts_traffic(self):
# Internal LB (wget) traffic test
ssh_client = self.ssh_into_VM(public_vm, public_ip)
- wget_file = self.wget_from_vm_cmd(
- ssh_client, int_lb_rule_1.sourceipaddress,
- self.test_data["http_rule"]["publicport"])
+ tries = 0
+ while tries < 120:
+ wget_file = self.wget_from_vm_cmd(
+ ssh_client, int_lb_rule_1.sourceipaddress,
+ self.test_data["http_rule"]["publicport"])
+ if wget_file != "":
+ break
+ self.debug("Waiting for the InternalLbVm in the Internal tier to "
+ "be fully resolved for (wget) traffic test...")
+ time.sleep(5)
+ tries += 1
# Verifying Internal LB (wget) traffic test
self.verify_lb_wget_file(
@@ -2128,16 +2145,15 @@ def test_07_nuage_internallb_vpc_network_restarts_traffic(self):
# Internal LB (wget) traffic test
ssh_client = self.ssh_into_VM(public_vm, public_ip)
tries = 0
- while tries < 25:
+ while tries < 120:
wget_file = self.wget_from_vm_cmd(
ssh_client, int_lb_rule_1.sourceipaddress,
self.test_data["http_rule"]["publicport"])
if wget_file != "":
break
- self.debug("Waiting for the InternalLbVm and all the VMs in the "
- "Internal tier to be fully resolved for (wget) traffic "
- "test...")
- time.sleep(60)
+ self.debug("Waiting for the InternalLbVm in the Internal tier to "
+ "be fully resolved for (wget) traffic test...")
+ time.sleep(5)
tries += 1
# Verifying Internal LB (wget) traffic test
@@ -2489,11 +2505,20 @@ def test_08_nuage_internallb_appliance_operations_traffic(self):
# Internal LB (wget) traffic test
ssh_client = self.ssh_into_VM(public_vm, public_ip)
- wget_file = self.wget_from_vm_cmd(
- ssh_client, int_lb_rule_1.sourceipaddress,
- self.test_data["http_rule"]["publicport"])
+ tries = 0
+ while tries < 120:
+ wget_file = self.wget_from_vm_cmd(
+ ssh_client, int_lb_rule_1.sourceipaddress,
+ self.test_data["http_rule"]["publicport"])
+ if wget_file != "":
+ break
+ self.debug("Waiting for the InternalLbVm in the Internal tier to "
+ "be fully resolved for (wget) traffic test...")
+ time.sleep(5)
+ tries += 1
# Verifying Internal LB (wget) traffic test
+ # Bug CLOUDSTACK-9837
self.verify_lb_wget_file(
wget_file, [internal_vm, internal_vm_1, internal_vm_2])
@@ -2556,9 +2581,17 @@ def test_08_nuage_internallb_appliance_operations_traffic(self):
# Internal LB (wget) traffic test
ssh_client = self.ssh_into_VM(public_vm, public_ip)
- wget_file = self.wget_from_vm_cmd(
- ssh_client, int_lb_rule_1.sourceipaddress,
- self.test_data["http_rule"]["publicport"])
+ tries = 0
+ while tries < 120:
+ wget_file = self.wget_from_vm_cmd(
+ ssh_client, int_lb_rule_1.sourceipaddress,
+ self.test_data["http_rule"]["publicport"])
+ if wget_file != "":
+ break
+ self.debug("Waiting for the InternalLbVm in the Internal tier to "
+ "be fully resolved for (wget) traffic test...")
+ time.sleep(5)
+ tries += 1
# Verifying Internal LB (wget) traffic test
self.verify_lb_wget_file(
@@ -2611,9 +2644,17 @@ def test_08_nuage_internallb_appliance_operations_traffic(self):
# Internal LB (wget) traffic test
ssh_client = self.ssh_into_VM(public_vm, public_ip)
- wget_file = self.wget_from_vm_cmd(
- ssh_client, int_lb_rule_1.sourceipaddress,
- self.test_data["http_rule"]["publicport"])
+ tries = 0
+ while tries < 120:
+ wget_file = self.wget_from_vm_cmd(
+ ssh_client, int_lb_rule_1.sourceipaddress,
+ self.test_data["http_rule"]["publicport"])
+ if wget_file != "":
+ break
+ self.debug("Waiting for the InternalLbVm in the Internal tier to "
+ "be fully resolved for (wget) traffic test...")
+ time.sleep(5)
+ tries += 1
# Verifying Internal LB (wget) traffic test
self.verify_lb_wget_file(
diff --git a/test/integration/plugins/nuagevsp/test_nuage_vpc_network.py b/test/integration/plugins/nuagevsp/test_nuage_vpc_network.py
index 088517756f7..e1b51287096 100644
--- a/test/integration/plugins/nuagevsp/test_nuage_vpc_network.py
+++ b/test/integration/plugins/nuagevsp/test_nuage_vpc_network.py
@@ -59,11 +59,13 @@ def test_nuage_vpc_network(self):
# 5. Create a VPC Network with Nuage VSP VPC Network offering and the
# created ACL list, check if it is successfully created, is in the
# "Implemented" state, and is added to the VPC VR.
- # 6. Deploy a VM in the created VPC network, check if the VM is
+ # 6. Verify that the VPC VR has no Public IP and NIC as it is not the
+ # Source NAT service provider.
+ # 7. Deploy a VM in the created VPC network, check if the VM is
# successfully deployed and is in the "Running" state.
- # 7. Verify that the created ACL item is successfully implemented in
+ # 8. Verify that the created ACL item is successfully implemented in
# Nuage VSP.
- # 8. Delete all the created objects (cleanup).
+ # 9. Delete all the created objects (cleanup).
# Creating a VPC offering
self.debug("Creating Nuage VSP VPC offering...")
@@ -99,6 +101,11 @@ def test_nuage_vpc_network(self):
vr = self.get_Router(vpc_network)
self.check_Router_state(vr, state="Running")
+ # Verifying that the VPC VR has no public IP and NIC
+ self.verify_VRWithoutPublicIPNIC(vr)
+ # Verifying that the VPC has no src NAT ip
+ self.verify_vpc_has_no_src_nat(vpc)
+
# Deploying a VM in the VPC network
vm = self.create_VM(vpc_network)
self.check_VM_state(vm, state="Running")
diff --git a/test/integration/plugins/nuagevsp/test_nuage_vsp.py b/test/integration/plugins/nuagevsp/test_nuage_vsp.py
index 9f2d1f23456..54656fd1694 100644
--- a/test/integration/plugins/nuagevsp/test_nuage_vsp.py
+++ b/test/integration/plugins/nuagevsp/test_nuage_vsp.py
@@ -173,11 +173,13 @@ def test_nuage_vsp(self):
# 4. Deploy a VM in the created Isolated network, check if the Isolated
# network state is changed to "Implemented", and both the VM & VR
# are successfully deployed and are in the "Running" state.
- # 5. Deploy one more VM in the created Isolated network, check if the
+ # 5. Verify that the VPC VR has no Public IP and NIC as it is not the
+ # Source NAT service provider.
+ # 6. Deploy one more VM in the created Isolated network, check if the
# VM is successfully deployed and is in the "Running" state.
- # 6. Delete the created Isolated Network after destroying its VMs,
+ # 7. Delete the created Isolated Network after destroying its VMs,
# check if the Isolated network is successfully deleted.
- # 7. Delete all the created objects (cleanup).
+ # 8. Delete all the created objects (cleanup).
for zone in self.zones:
self.debug("Zone - %s" % zone.name)
@@ -206,6 +208,9 @@ def test_nuage_vsp(self):
self.check_Router_state(vr, state="Running")
self.check_VM_state(vm_1, state="Running")
+ # Verifying that the VR has no public IP and NIC
+ self.verify_VRWithoutPublicIPNIC(vr)
+
# VSD verification
self.verify_vsd_network(self.domain.id, network)
self.verify_vsd_router(vr)
diff --git a/test/integration/smoke/test_certauthority_root.py b/test/integration/smoke/test_certauthority_root.py
new file mode 100644
index 00000000000..45ffd52c0bb
--- /dev/null
+++ b/test/integration/smoke/test_certauthority_root.py
@@ -0,0 +1,229 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import *
+from marvin.cloudstackAPI import *
+from marvin.lib.utils import *
+from marvin.lib.base import *
+from marvin.lib.common import *
+
+from cryptography import x509
+from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.primitives import serialization
+from OpenSSL.crypto import FILETYPE_PEM, verify, X509
+
+PUBKEY_VERIFY=True
+try:
+ from OpenSSL.crypto import load_publickey
+except ImportError:
+ PUBKEY_VERIFY=False
+
+
+class TestCARootProvider(cloudstackTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ testClient = super(TestCARootProvider, cls).getClsTestClient()
+ cls.apiclient = testClient.getApiClient()
+ cls.services = testClient.getParsedTestDataConfig()
+ cls.hypervisor = cls.testClient.getHypervisorInfo()
+ cls.cleanup = []
+
+
+ @classmethod
+ def tearDownClass(cls):
+ try:
+ cleanup_resources(cls.apiclient, cls.cleanup)
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+
+
+ def setUp(self):
+ self.apiclient = self.testClient.getApiClient()
+ self.dbclient = self.testClient.getDbConnection()
+ self.cleanup = []
+
+
+ def tearDown(self):
+ try:
+ cleanup_resources(self.apiclient, self.cleanup)
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+
+
+ def getUpSystemVMHosts(self, hostId=None):
+ hosts = list_hosts(
+ self.apiclient,
+ type='SecondaryStorageVM',
+ state='Up',
+ resourcestate='Enabled',
+ id=hostId
+ )
+ return hosts
+
+
+ @attr(tags=['advanced', 'simulator', 'basic', 'sg'], required_hardware=False)
+ def test_list_ca_providers(self):
+ """
+ Tests default ca providers list
+ """
+ cmd = listCAProviders.listCAProvidersCmd()
+ response = self.apiclient.listCAProviders(cmd)
+ self.assertEqual(len(response), 1)
+ self.assertEqual(response[0].name, 'root')
+
+
+ def getCaCertificate(self):
+ cmd = listCaCertificate.listCaCertificateCmd()
+ cmd.provider = 'root'
+ response = self.apiclient.listCaCertificate(cmd)
+ return response.cacertificates.certificate
+
+
+ @attr(tags=['advanced', 'simulator', 'basic', 'sg'], required_hardware=False)
+ def test_list_ca_certificate(self):
+ """
+ Tests the ca certificate
+ """
+ certificate = self.getCaCertificate()
+ self.assertTrue(len(certificate) > 0)
+
+ cert = x509.load_pem_x509_certificate(str(certificate), default_backend())
+ self.assertEqual(cert.signature_hash_algorithm.name, 'sha256')
+ self.assertEqual(cert.issuer.get_attributes_for_oid(x509.oid.NameOID.COMMON_NAME)[0].value, 'ca.cloudstack.apache.org')
+
+
+ @attr(tags=['advanced', 'simulator', 'basic', 'sg'], required_hardware=False)
+ def test_issue_certificate_without_csr(self):
+ """
+ Tests issuance of a certificate
+ """
+ cmd = issueCertificate.issueCertificateCmd()
+ cmd.domain = 'apache.org,cloudstack.apache.org'
+ cmd.ipaddress = '10.1.1.1,10.2.2.2'
+ cmd.provider = 'root'
+
+ response = self.apiclient.issueCertificate(cmd)
+ self.assertTrue(len(response.privatekey) > 0)
+ self.assertTrue(len(response.cacertificates) > 0)
+ self.assertTrue(len(response.certificate) > 0)
+
+ cert = x509.load_pem_x509_certificate(str(response.certificate), default_backend())
+
+ # Validate basic certificate attributes
+ self.assertEqual(cert.signature_hash_algorithm.name, 'sha256')
+ self.assertEqual(cert.subject.get_attributes_for_oid(x509.oid.NameOID.COMMON_NAME)[0].value, 'apache.org')
+
+ # Validate alternative names
+ altNames = cert.extensions.get_extension_for_oid(x509.oid.ExtensionOID.SUBJECT_ALTERNATIVE_NAME)
+ for domain in cmd.domain.split(','):
+ self.assertTrue(domain in altNames.value.get_values_for_type(x509.DNSName))
+ for address in cmd.ipaddress.split(','):
+ self.assertTrue(address in map(lambda x: str(x), altNames.value.get_values_for_type(x509.IPAddress)))
+
+ # Validate certificate against CA public key
+ global PUBKEY_VERIFY
+ if not PUBKEY_VERIFY:
+ return
+ caCert = x509.load_pem_x509_certificate(str(self.getCaCertificate()), default_backend())
+ x = X509()
+ x.set_pubkey(load_publickey(FILETYPE_PEM, str(caCert.public_key().public_bytes(serialization.Encoding.PEM, serialization.PublicFormat.SubjectPublicKeyInfo))))
+ verify(x, cert.signature, cert.tbs_certificate_bytes, cert.signature_hash_algorithm.name)
+
+
+ @attr(tags=['advanced', 'simulator', 'basic', 'sg'], required_hardware=False)
+ def test_issue_certificate_with_csr(self):
+ """
+ Tests issuance of a certificate
+ """
+ cmd = issueCertificate.issueCertificateCmd()
+ cmd.csr = "-----BEGIN CERTIFICATE REQUEST-----\nMIIBHjCByQIBADBkMQswCQYDVQQGEwJJTjELMAkGA1UECAwCSFIxETAPBgNVBAcM\nCEd1cnVncmFtMQ8wDQYDVQQKDAZBcGFjaGUxEzARBgNVBAsMCkNsb3VkU3RhY2sx\nDzANBgNVBAMMBnYtMS1WTTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQD46KFWKYrJ\nF43Y1oqWUfrl4mj4Qm05Bgsi6nuigZv7ufiAKK0nO4iJKdRa2hFMUvBi2/bU3IyY\nNvg7cdJsn4K9AgMBAAGgADANBgkqhkiG9w0BAQUFAANBAIta9glu/ZSjA/ncyXix\nyDOyAKmXXxsRIsdrEuIzakUuJS7C8IG0FjUbDyIaiwWQa5x+Lt4oMqCmpNqRzaGP\nfOo=\n-----END CERTIFICATE REQUEST-----"
+ cmd.provider = 'root'
+
+ response = self.apiclient.issueCertificate(cmd)
+ self.assertTrue(response.privatekey is None)
+ self.assertTrue(len(response.cacertificates) > 0)
+ self.assertTrue(len(response.certificate) > 0)
+
+ cert = x509.load_pem_x509_certificate(str(response.certificate), default_backend())
+
+ # Validate basic certificate attributes
+ self.assertEqual(cert.signature_hash_algorithm.name, 'sha256')
+ self.assertEqual(cert.subject.get_attributes_for_oid(x509.oid.NameOID.COMMON_NAME)[0].value, 'v-1-VM')
+
+ # Validate certificate against CA public key
+ global PUBKEY_VERIFY
+ if not PUBKEY_VERIFY:
+ return
+ caCert = x509.load_pem_x509_certificate(str(self.getCaCertificate()), default_backend())
+ x = X509()
+ x.set_pubkey(load_publickey(FILETYPE_PEM, str(caCert.public_key().public_bytes(serialization.Encoding.PEM, serialization.PublicFormat.SubjectPublicKeyInfo))))
+ verify(x, cert.signature, cert.tbs_certificate_bytes, cert.signature_hash_algorithm.name)
+
+
+ @attr(tags=['advanced', 'simulator', 'basic', 'sg'], required_hardware=False)
+ def test_revoke_certificate(self):
+ """
+ Tests certificate revocation
+ """
+ cmd = revokeCertificate.revokeCertificateCmd()
+ cmd.serial = 'abc123' # hex value
+ cmd.cn = 'example.com'
+ cmd.provider = 'root'
+
+ self.dbclient.execute("delete from crl where serial='%s'" % cmd.serial)
+
+ response = self.apiclient.revokeCertificate(cmd)
+ self.assertTrue(response.success)
+
+ crl = self.dbclient.execute("select serial, cn from crl where serial='%s'" % cmd.serial)[0]
+ self.assertEqual(crl[0], cmd.serial)
+ self.assertEqual(crl[1], cmd.cn)
+
+
+ @attr(tags=['advanced', 'simulator', 'basic', 'sg'], required_hardware=False)
+ def test_provision_certificate(self):
+ """
+ Tests certificate provisioning
+ """
+ hosts = self.getUpSystemVMHosts()
+ if not hosts or len(hosts) < 1:
+ raise self.skipTest("No Up systemvm hosts found, skipping test")
+
+ host = hosts[0]
+
+ cmd = provisionCertificate.provisionCertificateCmd()
+ cmd.hostid = host.id
+ cmd.reconnect = True
+ cmd.provider = 'root'
+
+ response = self.apiclient.provisionCertificate(cmd)
+ self.assertTrue(response.success)
+
+ if self.hypervisor.lower() == 'simulator':
+ hosts = self.getUpSystemVMHosts(host.id)
+ self.assertTrue(hosts is None or len(hosts) == 0)
+ else:
+ def checkHostIsUp(hostId):
+ hosts = self.getUpSystemVMHosts(host.id)
+ return (hosts is not None), hosts
+ result, hosts = wait_until(1, 30, checkHostIsUp, host.id)
+ if result:
+ self.assertTrue(len(hosts) == 1)
+ else:
+ self.fail("Failed to have systemvm host in Up state after cert provisioning")
diff --git a/test/integration/smoke/test_deploy_vm_root_resize.py b/test/integration/smoke/test_deploy_vm_root_resize.py
index 30a1a94e6f2..a41d29f4c18 100755
--- a/test/integration/smoke/test_deploy_vm_root_resize.py
+++ b/test/integration/smoke/test_deploy_vm_root_resize.py
@@ -28,6 +28,7 @@
from marvin.lib.common import get_zone, get_domain, get_template,\
list_volumes,list_storage_pools,list_configurations
from marvin.codes import FAILED,INVALID_INPUT
+from marvin.cloudstackAPI import *
from nose.plugins.attrib import attr
from marvin.sshClient import SshClient
import time
@@ -102,15 +103,6 @@ def setUpClass(cls):
cls.updateclone = True
cls.restartreq = True
- cls.tempobj = Template.register(cls.api_client,
- cls.services["templateregister"],
- hypervisor=cls.hypervisor,
- zoneid=cls.zone.id,
- account=cls.account.name,
- domainid=cls.domain.id
- )
- cls.tempobj.download(cls.api_client)
-
for strpool in list_pool_resp:
if strpool.type.lower() == "vmfs" or strpool.type.lower()== "networkfilesystem":
list_config_storage_response = list_configurations(
@@ -133,6 +125,11 @@ def setUpClass(cls):
break
if cls.restartreq:
cls.restartServer()
+
+ #Giving 30 seconds to management to warm-up,
+ #Experienced failures when trying to deploy a VM exactly when management came up
+ time.sleep(30)
+
#create a service offering
cls.service_offering = ServiceOffering.create(
cls.api_client,
@@ -159,7 +156,6 @@ def tearDownClass(cls):
"vmware.root.disk.controller",
value=cls.defaultdiskcontroller)
-
cleanup_resources(cls.api_client, cls._cleanup)
except Exception as e:
raise Exception("Warning: Exception during cleanup : %s" % e)
@@ -197,10 +193,20 @@ def restartServer(cls):
command = "service cloudstack-management start"
sshClient.execute(command)
- #time.sleep(cls.services["sleep"])
- time.sleep(300)
+ #Waits for management to come up in 5 mins, when it's up it will continue
+ timeout = time.time() + 300
+ while time.time() < timeout:
+ if cls.isManagementUp() is True: return
+ time.sleep(5)
+ return cls.fail("Management server did not come up, failing")
- return
+ @classmethod
+ def isManagementUp(cls):
+ try:
+ cls.api_client.listInfrastructure(listInfrastructure.listInfrastructureCmd())
+ return True
+ except Exception:
+ return False
@attr(tags = ['advanced', 'basic', 'sg'], required_hardware="true")
def test_00_deploy_vm_root_resize(self):
@@ -212,7 +218,6 @@ def test_00_deploy_vm_root_resize(self):
# 3. Rejects non-supported hypervisor types
"""
-
newrootsize = (self.template.size >> 30) + 2
if(self.hypervisor.lower() == 'kvm' or self.hypervisor.lower() ==
'xenserver'or self.hypervisor.lower() == 'vmware' ):
@@ -224,7 +229,7 @@ def test_00_deploy_vm_root_resize(self):
accountid=self.account.name,
domainid=self.domain.id,
serviceofferingid=self.services_offering_vmware.id,
- templateid=self.tempobj.id,
+ templateid=self.template.id,
rootdisksize=newrootsize
)
@@ -239,9 +244,6 @@ def test_00_deploy_vm_root_resize(self):
rootdisksize=newrootsize
)
-
-
-
list_vms = VirtualMachine.list(self.apiclient, id=self.virtual_machine.id)
self.debug(
"Verify listVirtualMachines response for virtual machine: %s" \
@@ -303,7 +305,7 @@ def test_00_deploy_vm_root_resize(self):
zoneid=self.zone.id,
domainid=self.account.domainid,
serviceofferingid=self.service_offering.id,
- templateid=self.tempobj.id,
+ templateid=self.template.id,
rootdisksize=newrootsize
)
except Exception as ex:
@@ -321,7 +323,6 @@ def test_01_deploy_vm_root_resize(self):
newrootsize=0
success=False
-
if(self.hypervisor.lower() == 'kvm' or self.hypervisor.lower() ==
'xenserver'or self.hypervisor.lower() == 'vmware' ):
try:
@@ -332,7 +333,7 @@ def test_01_deploy_vm_root_resize(self):
accountid=self.account.name,
domainid=self.domain.id,
serviceofferingid=self.services_offering_vmware.id,
- templateid=self.tempobj.id,
+ templateid=self.template.id,
rootdisksize=newrootsize
)
@@ -355,8 +356,6 @@ def test_01_deploy_vm_root_resize(self):
else:
self.debug("test 01 does not support hypervisor type " + self.hypervisor)
-
-
@attr(tags = ['advanced', 'basic', 'sg'], required_hardware="true", BugId="CLOUDSTACK-6984")
def test_02_deploy_vm_root_resize(self):
"""Test proper failure to deploy virtual machine with rootdisksize less than template size
@@ -375,7 +374,7 @@ def test_02_deploy_vm_root_resize(self):
accountid=self.account.name,
domainid=self.domain.id,
serviceofferingid=self.services_offering_vmware.id,
- templateid=self.tempobj.id,
+ templateid=self.template.id,
rootdisksize=newrootsize
)
@@ -406,3 +405,4 @@ def tearDown(self):
except Exception as e:
self.debug("Warning! Exception in tearDown: %s" % e)
+
diff --git a/test/integration/smoke/test_dynamicroles.py b/test/integration/smoke/test_dynamicroles.py
index 99614374553..5d105f6a427 100644
--- a/test/integration/smoke/test_dynamicroles.py
+++ b/test/integration/smoke/test_dynamicroles.py
@@ -394,6 +394,46 @@ def validate_permissions_list(permissions):
rule.update(self.apiclient, ruleorder=",".join(map(lambda x: x.id, permissions)))
validate_permissions_list(permissions)
+ @attr(tags=['advanced', 'simulator', 'basic', 'sg'], required_hardware=False)
+ def test_rolepermission_lifecycle_update_permission(self):
+ """
+ Tests update of Allow to Deny permission of a rule
+ """
+ permissions = [self.rolepermission]
+
+ rule = permissions.pop(0)
+ rule.update(self.apiclient, ruleid=rule.id, permission='deny')
+
+ list_rolepermissions = RolePermission.list(self.apiclient, roleid=self.role.id)
+ self.assertEqual(
+ list_rolepermissions[0].permission,
+ 'deny',
+ msg="List of role permissions do not match created list of permissions"
+ )
+
+ rule.update(self.apiclient, ruleid=rule.id, permission='allow')
+
+ list_rolepermissions = RolePermission.list(self.apiclient, roleid=self.role.id)
+ self.assertEqual(
+ list_rolepermissions[0].permission,
+ 'allow',
+ msg="List of role permissions do not match created list of permissions"
+ )
+
+ @attr(tags=['advanced', 'simulator', 'basic', 'sg'], required_hardware=False)
+ def test_rolepermission_lifecycle_update_permission_negative(self):
+ """
+ Tests negative test for setting incorrect value as permission
+ """
+ permissions = [self.rolepermission]
+
+ rule = permissions.pop(0)
+ try:
+ rule.update(self.apiclient, ruleid=rule.id, permission='some_other_value')
+ except Exception:
+ pass
+ else:
+ self.fail("Negative test: Setting permission to 'some_other_value' should not be successful, failing")
@attr(tags=['advanced', 'simulator', 'basic', 'sg'], required_hardware=False)
def test_rolepermission_lifecycle_concurrent_updates(self):
diff --git a/test/integration/smoke/test_host_annotations.py b/test/integration/smoke/test_host_annotations.py
new file mode 100644
index 00000000000..91c3409d27d
--- /dev/null
+++ b/test/integration/smoke/test_host_annotations.py
@@ -0,0 +1,178 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+""" BVT tests for Hosts and Clusters
+"""
+#Import Local Modules
+import marvin
+from marvin.cloudstackTestCase import *
+from marvin.cloudstackAPI import *
+from marvin.lib.utils import *
+from marvin.lib.base import *
+from marvin.lib.common import *
+from marvin.lib.utils import (random_gen)
+from nose.plugins.attrib import attr
+
+#Import System modules
+import time
+
+_multiprocess_shared_ = True
+
+class TestHostAnnotations(cloudstackTestCase):
+
+ def setUp(self):
+ self.apiclient = self.testClient.getApiClient()
+ self.services = self.testClient.getParsedTestDataConfig()
+ self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests())
+ self.host = list_hosts(self.apiclient,
+ zoneid=self.zone.id,
+ type='Routing')[0]
+ self.cleanup = []
+ self.added_annotations = []
+
+ return
+
+ def tearDown(self):
+ try:
+ #Clean up
+ cleanup_resources(self.apiclient, self.cleanup)
+ self.cleanAnnotations()
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+ return
+
+ def cleanAnnotations(self):
+ """Remove annotations"""
+ for annotation in self.added_annotations:
+ self.removeAnnotation(annotation.annotation.id)
+
+ def addAnnotation(self, annotation):
+ cmd = addAnnotation.addAnnotationCmd()
+ cmd.entityid = self.host.id
+ cmd.entitytype = "HOST"
+ cmd.annotation = annotation
+
+ self.added_annotations.append(self.apiclient.addAnnotation(cmd))
+
+ return self.added_annotations[-1]
+
+ def removeAnnotation(self, id):
+ cmd = removeAnnotation.removeAnnotationCmd()
+ cmd.id = id
+
+ return self.apiclient.removeAnnotation(cmd)
+
+ def getHostAnnotation(self, hostId):
+ host = list_hosts(self.apiclient,
+ zoneid=self.zone.id,
+ type='Routing')[0]
+ return host.annotation
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_01_add_annotation(self):
+ """Testing the addAnnotations API ability to add an annoatation per host"""
+ self.addAnnotation("annotation1")
+ self.assertEqual(self.added_annotations[-1].annotation.annotation, "annotation1")
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_02_add_multiple_annotations(self):
+ """Testing the addAnnotations API ability to add an annoatation per host
+ when there are annotations already.
+ And only the last one stands as annotation attribute on host level."""
+ self.addAnnotation("annotation1")
+ self.assertEqual(self.added_annotations[-1].annotation.annotation, "annotation1")
+
+ # Adds sleep of 1 second just to be sure next annotation will not be created in the same second.
+ time.sleep(1)
+ self.addAnnotation("annotation2")
+ self.assertEqual(self.added_annotations[-1].annotation.annotation, "annotation2")
+
+ # Adds sleep of 1 second just to be sure next annotation will not be created in the same second.
+ time.sleep(1)
+ self.addAnnotation("annotation3")
+ self.assertEqual(self.added_annotations[-1].annotation.annotation, "annotation3")
+
+ #Check that the last one is visible in host details
+ self.assertEqual(self.getHostAnnotation(self.host.id), "annotation3")
+ print
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_03_user_role_dont_see_annotations(self):
+ """Testing the annotations api are restricted to users"""
+
+ self.addAnnotation("annotation1")
+ self.assertEqual(self.added_annotations[-1].annotation.annotation, "annotation1")
+
+ self.account = Account.create(
+ self.apiclient,
+ self.services["account"],
+ )
+ self.cleanup.append(self.account)
+
+ userApiClient = self.testClient.getUserApiClient(self.account.name, 'ROOT', 'User')
+
+ cmd = addAnnotation.addAnnotationCmd()
+ cmd.entityid = self.host.id
+ cmd.entitytype = "HOST"
+ cmd.annotation = "test"
+
+ try:
+ self.added_annotations.append(userApiClient.addAnnotation(cmd))
+ except Exception:
+ pass
+ else:
+ self.fail("AddAnnotation is allowed for User")
+
+ cmd = listAnnotations.listAnnotationsCmd()
+ try:
+ userApiClient.listAnnotations(cmd)
+ except Exception:
+ pass
+ else:
+ self.fail("ListAnnotations is allowed for User")
+
+ cmd = removeAnnotation.removeAnnotationCmd()
+ cmd.id = self.added_annotations[-1].annotation.id
+ try:
+ userApiClient.removeAnnotation(cmd)
+ except Exception:
+ pass
+ else:
+ self.fail("RemoveAnnotation is allowed for User")
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_04_remove_annotations(self):
+ """Testing the deleteAnnotation API ability to delete annotation"""
+ self.addAnnotation("annotation1")
+ self.removeAnnotation(self.added_annotations[-1].annotation.id)
+ del self.added_annotations[-1]
+
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_05_add_annotation_for_invalid_entityType(self):
+ cmd = addAnnotation.addAnnotationCmd()
+ cmd.entityid = self.host.id
+ cmd.entitytype = "BLA"
+ cmd.annotation = "annotation"
+
+ try:
+ self.apiclient.addAnnotation(cmd)
+ except Exception as f:
+ pass
+ else:
+ self.fail("AddAnnotation is allowed for on an unknown entityType")
+
+ return self.added_annotations[-1]
diff --git a/test/integration/smoke/test_hostha_kvm.py b/test/integration/smoke/test_hostha_kvm.py
new file mode 100644
index 00000000000..cc44426227b
--- /dev/null
+++ b/test/integration/smoke/test_hostha_kvm.py
@@ -0,0 +1,626 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import marvin
+from marvin.cloudstackTestCase import *
+from marvin.cloudstackAPI import *
+from marvin.lib.utils import *
+from marvin.lib.base import *
+from marvin.lib.common import *
+from nose.plugins.attrib import attr
+
+import random
+
+from ipmisim.ipmisim import IpmiServerContext, IpmiServer, ThreadedIpmiServer
+
+import random
+import socket
+import sys
+import thread
+import time
+
+
+class TestHAKVM(cloudstackTestCase):
+ """ Test cases for host HA using KVM host(s)
+ """
+
+ def setUp(self):
+ self.testClient = super(TestHAKVM, self).getClsTestClient()
+ self.apiclient = self.testClient.getApiClient()
+ self.dbclient = self.testClient.getDbConnection()
+ self.services = self.testClient.getParsedTestDataConfig()
+ self.logger = logging.getLogger('TestHAKVM')
+
+ #Get Zone specifics
+ self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests())
+ self.hypervisor = self.testClient.getHypervisorInfo()
+ self.host = self.getHost()
+ self.hostConfig = self.config.__dict__["zones"][0].__dict__["pods"][0].__dict__["clusters"][0].__dict__["hosts"][0].__dict__
+ self.mgtSvrDetails = self.config.__dict__["mgtSvr"][0].__dict__
+ self.cluster_id = self.host.clusterid
+
+ # Cleanup any existing configs
+ self.dbclient.execute("delete from ha_config where resource_type='Host'")
+
+ # use random port for ipmisim
+ self.fakeMsId = random.randint(10000, 99999) * random.randint(10, 20)
+ s = socket.socket()
+ s.bind(('', 0))
+ self.serverPort = s.getsockname()[1]
+ s.close()
+
+ # Set Cluster-level setting in order to run tests faster
+ self.updateConfiguration("kvm.ha.activity.check.failure.ratio", "0.6")
+ self.updateConfiguration("kvm.ha.activity.check.interval", "8")
+ self.updateConfiguration("kvm.ha.activity.check.max.attempts", "5")
+ self.updateConfiguration("kvm.ha.activity.check.timeout", "30")
+ self.updateConfiguration("kvm.ha.degraded.max.period", "30")
+ self.updateConfiguration("kvm.ha.fence.timeout", "30")
+ self.updateConfiguration("kvm.ha.health.check.timeout", "30")
+ self.updateConfiguration("kvm.ha.recover.failure.threshold", "2")
+ self.updateConfiguration("kvm.ha.recover.timeout", "30")
+ self.updateConfiguration("kvm.ha.recover.wait.period", "30")
+
+ self.service_offering = ServiceOffering.create(
+ self.apiclient,
+ self.services["service_offerings"]["hasmall"]
+ )
+
+ self.template = get_template(
+ self.apiclient,
+ self.zone.id,
+ self.services["ostype"]
+ )
+
+ self.configureAndDisableHostHa()
+ self.cleanup = [self.service_offering]
+
+ def updateConfiguration(self, name, value):
+ cmd = updateConfiguration.updateConfigurationCmd()
+ cmd.name = name
+ cmd.value = value
+ cmd.clusterid = self.cluster_id
+ self.apiclient.updateConfiguration(cmd)
+
+ def getFakeMsId(self):
+ return self.fakeMsId
+
+ def getFakeMsRunId(self):
+ return self.fakeMsId * 1000
+
+ def tearDown(self):
+ self.configureAndDisableHostHa()
+ self.host = None
+ try:
+ self.dbclient.execute("delete from mshost_peer where peer_runid=%s" % self.getFakeMsRunId())
+ self.dbclient.execute("delete from mshost where runid=%s" % self.getFakeMsRunId())
+ self.dbclient.execute("delete from cluster_details where name='resourceHAEnabled'")
+ self.dbclient.execute("delete from data_center_details where name='resourceHAEnabled'")
+ self.dbclient.execute("delete from ha_config where resource_type='Host'")
+ self.dbclient.execute("delete from oobm where port=%d" % self.getIpmiServerPort())
+ self.dbclient.execute("delete from mshost_peer where peer_runid=%s" % self.getFakeMsRunId())
+ self.dbclient.execute("delete from mshost where runid=%s" % self.getFakeMsRunId())
+ self.dbclient.execute("delete from cluster_details where name='outOfBandManagementEnabled'")
+ self.dbclient.execute("delete from data_center_details where name='outOfBandManagementEnabled'")
+ cleanup_resources(self.apiclient, self.cleanup)
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+
+ def getHostHaEnableCmd(self):
+ cmd = enableHAForHost.enableHAForHostCmd()
+ cmd.hostid = self.host.id
+ return cmd
+
+ def getHost(self, hostId=None):
+ response = list_hosts(
+ self.apiclient,
+ type='Routing',
+ hypervisor='kvm',
+ id=hostId
+ )
+ # Check if more than one kvm hosts are available in order to successfully configure host-ha
+ if response and len(response) > 0:
+ self.host = response[0]
+ return self.host
+ raise self.skipTest("Not enough KVM hosts found, skipping host-ha test")
+
+ def getHostHaConfigCmd(self, provider='kvmhaprovider'):
+ cmd = configureHAForHost.configureHAForHostCmd()
+ cmd.provider = provider
+ cmd.hostid = self.host.id
+ return cmd
+
+ def getHostHaDisableCmd(self):
+ cmd = disableHAForHost.disableHAForHostCmd()
+ cmd.hostid = self.host.id
+ return cmd
+
+ def configureAndEnableHostHa(self):
+ #Adding sleep between configuring and enabling
+ self.apiclient.configureHAForHost(self.getHostHaConfigCmd())
+ response = self.apiclient.enableHAForHost(self.getHostHaEnableCmd())
+ self.assertEqual(response.haenable, True)
+
+ def configureAndDisableHostHa(self):
+ self.apiclient.configureHAForHost(self.getHostHaConfigCmd())
+ cmd = self.getHostHaDisableCmd()
+ cmd.hostid = self.host.id
+ response = self.apiclient.disableHAForHost(cmd)
+ self.assertEqual(response.hostid, cmd.hostid)
+ self.assertEqual(response.haenable, False)
+
+ def enableHostHa(self, hostId):
+ cmd = self.getHostHaEnableCmd()
+ cmd.hostid = hostId
+ response = self.apiclient.enableHAForHost(cmd)
+ self.assertEqual(response.hostid, cmd.hostid)
+ self.assertEqual(response.haenable, True)
+ return response
+
+ def disableAgent(self):
+ SshClient(self.host.ipaddress, port=22, user=self.hostConfig["username"], passwd=self.hostConfig["password"]).execute\
+ ("systemctl disable cloudstack-agent || chkconfig cloudstack-agent off")
+
+ def resetHost(self):
+ SshClient(self.host.ipaddress, port=22, user=self.hostConfig["username"],
+ passwd=self.hostConfig["password"]).execute \
+ ("reboot")
+
+ def enableAgent(self):
+ SshClient(self.host.ipaddress, port=22, user=self.hostConfig["username"], passwd=self.hostConfig["password"]).execute\
+ ("systemctl enable cloudstack-agent || chkconfig cloudstack-agent on")
+
+ def waitUntilHostInState(self, state="Available", interval=3):
+ def checkForState(expectedState):
+ response = self.getHost(self.host.id)
+ print("checkForState:: expected=%s, actual=%s" % (state, response.hostha))
+ return response.hostha.hastate == expectedState, None
+
+ res, _ = wait_until(interval, 200, checkForState, state)
+ if not res:
+ self.fail("Failed to see host ha state in :" + state)
+
+ def deployVM(self):
+ try:
+ vm = VirtualMachine.create(
+ self.apiclient,
+ services=self.services["virtual_machine"],
+ serviceofferingid=self.service_offering.id,
+ templateid=self.template.id,
+ zoneid=self.zone.id,
+ hostid = self.host.id,
+ method="POST"
+ )
+ self.cleanup.append(vm)
+ except Exception as e:
+ raise self.skipTest("Failed to deploy VM, skipping kvm host-ha test case")
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="true")
+ def test_disable_oobm_ha_state_ineligible(self):
+ """
+ Tests that when HA is enabled for a host, if oobm is disabled HA State should turn into Ineligible
+ """
+ self.logger.debug("Starting test_disable_oobm_ha_state_ineligible")
+
+ # Enable ha for host
+ self.configureAndEnableHostHa()
+
+ # Disable OOBM
+ self.apiclient.configureOutOfBandManagement(self.getOobmConfigCmd())
+ oobm_cmd = self.getOobmDisableCmd()
+ oobm_cmd.hostid = self.host.id
+ response = self.apiclient.disableOutOfBandManagementForHost(oobm_cmd)
+ self.assertEqual(response.hostid, oobm_cmd.hostid)
+ self.assertEqual(response.enabled, False)
+
+ response = self.getHost(hostId=self.host.id).outofbandmanagement
+ self.assertEqual(response.powerstate, 'Disabled')
+
+ # Verify HA State is Ineligeble
+ self.waitUntilHostInState("Ineligible")
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="true")
+ def test_hostha_configure_default_driver(self):
+ """
+ Tests host-ha configuration with valid data
+ """
+ self.logger.debug("Starting test_hostha_configure_default_driver")
+
+ cmd = self.getHostHaConfigCmd()
+ response = self.apiclient.configureHAForHost(cmd)
+ self.assertEqual(response.hostid, cmd.hostid)
+ self.assertEqual(response.haprovider, cmd.provider.lower())
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="true")
+ def test_hostha_enable_ha_when_host_disabled(self):
+ """
+ Tests Enable HA when host is disconnected, should be Ineligible
+ """
+ self.logger.debug("Starting test_hostha_enable_ha_when_host_disabled")
+
+ # Enable HA
+ self.configureAndEnableHostHa()
+
+ # Disable Host
+ self.disableHost(self.host.id)
+
+ # Check HA State
+ try:
+ self.waitUntilHostInState("Ineligible")
+ except Exception as e:
+ self.enableHost(self.host.id)
+ self.fail(e)
+
+ # Enable Host
+ self.enableHost(self.host.id)
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="true")
+ def test_hostha_enable_ha_when_host_in_maintenance(self):
+ """
+ Tests Enable HA when host is in Maintenance mode, should be Ineligible
+ """
+ self.logger.debug("Starting test_hostha_enable_ha_when_host_in_maintenance")
+
+ # Enable HA
+ self.configureAndEnableHostHa()
+
+ # Prepare for maintenance Host
+ self.setHostToMaintanance(self.host.id)
+
+ # Check HA State
+ try:
+ self.waitUntilHostInState("Ineligible")
+ except Exception as e:
+ self.cancelMaintenance()
+ self.fail(e)
+
+ # Enable Host
+ self.cancelMaintenance()
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="true")
+ def test_hostha_enable_ha_when_host_disconected(self):
+ """
+ Tests Enable HA when host is disconnected, should be Ineligible
+ """
+ self.logger.debug("Starting test_hostha_enable_ha_when_host_disconected")
+
+ # Enable HA
+ self.apiclient.configureHAForHost(self.getHostHaConfigCmd())
+ cmd = self.getHostHaEnableCmd()
+ cmd.hostid = self.host.id
+ enable = self.apiclient.enableHAForHost(cmd)
+ self.assertEqual(enable.hostid, cmd.hostid)
+ self.assertEqual(enable.haenable, True)
+
+ # Make Host Disconnected
+ self.killAgent()
+
+ # Check HA State
+ try:
+ self.waitUntilHostInState("Ineligible")
+ except Exception as e:
+ self.startAgent()
+ self.fail(e)
+
+ # Enable Host
+ self.startAgent()
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="true")
+ def test_remove_ha_provider_not_possible(self):
+ """
+ Tests HA Provider should be possible to be removed when HA is enabled
+ """
+ self.logger.debug("Starting test_remove_ha_provider_not_possible")
+
+
+ # Enable HA
+ self.apiclient.configureHAForHost(self.getHostHaConfigCmd())
+ cmd = self.getHostHaEnableCmd()
+ cmd.hostid = self.host.id
+ enable = self.apiclient.enableHAForHost(cmd)
+ self.assertEqual(enable.hostid, cmd.hostid)
+ self.assertEqual(enable.haenable, True)
+
+ try:
+ self.apiclient.configureHAForHost(self.getHostHaConfigCmd(''))
+ except Exception:
+ pass
+ else:
+ self.fail("Expected an exception to be thrown, failing")
+
+ @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="true")
+ def test_hostha_kvm_host_degraded(self):
+ """
+ Tests degraded HA state when agent is stopped/killed
+ """
+
+ self.configureAndStartIpmiServer()
+ self.assertIssueCommandState('ON', 'On')
+ self.configureAndEnableHostHa()
+
+ self.deployVM()
+
+ # Start with the available state
+ self.waitUntilHostInState("Available")
+
+ # SSH into the KVM Host and executes kill -9 of the agent
+ self.stopAgent()
+
+ # Check if host would go into Suspect state
+ try:
+ self.waitUntilHostInState("Suspect")
+ except Exception as e:
+ self.startAgent()
+ raise Exception("Warning: Exception during test execution : %s" % e)
+
+ # Checks if the host would turn into Degraded
+ try:
+ self.waitUntilHostInState("Degraded")
+ except Exception as e:
+ self.startAgent()
+ raise Exception("Warning: Exception during test execution : %s" % e)
+
+ self.startAgent()
+ self.waitUntilHostInState("Available")
+
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="true")
+ def test_hostha_kvm_host_recovering(self):
+ """
+ Tests recovery and fencing HA state transitions
+ """
+
+ self.configureAndStartIpmiServer()
+ self.assertIssueCommandState('ON', 'On')
+ self.configureAndEnableHostHa()
+
+ self.deployVM()
+
+ # Start with the available state
+ self.waitUntilHostInState("Available")
+
+ # Kill host by triggering a fault
+ self.killAgent()
+ self.disableAgent()
+ self.resetHost()
+
+ # Check if host would go into Suspect state
+ try:
+ self.waitUntilHostInState("Suspect")
+ except Exception as e:
+ self.startAgent()
+ raise Exception("Warning: Exception during test execution : %s" % e)
+
+ # Checks if the host would turn into Recovered
+ try:
+ self.waitUntilHostInState("Recovered")
+ except Exception as e:
+ self.startAgent()
+ raise Exception("Warning: Exception during test execution : %s" % e)
+
+ self.enableAgent()
+ self.startAgent()
+ self.waitUntilHostInState("Available")
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="true")
+ def test_hostha_kvm_host_fencing(self):
+ """
+ Tests fencing/fenced HA state when host crashes
+ """
+ self.logger.debug("Starting test_ha_kvm_host_fencing")
+
+
+ self.configureAndStartIpmiServer()
+ self.assertIssueCommandState('ON', 'On')
+ self.configureAndEnableHostHa()
+
+ self.deployVM()
+
+ # Start with the available state
+ self.waitUntilHostInState("Available")
+
+ # Fail oobm commands
+ cmd = self.getOobmConfigCmd()
+ cmd.address = "1.1.1.1"
+ self.apiclient.configureOutOfBandManagement(cmd)
+
+ # Kill host by triggering a fault
+ self.killAgent()
+ self.disableAgent()
+ self.resetHost()
+
+ # Check if host would go into Suspect state
+ try:
+ self.waitUntilHostInState("Suspect")
+ except Exception as e:
+ self.startAgent()
+ raise Exception("Warning: Exception during test execution : %s" % e)
+
+ # Checks if the host would turn into Fencing
+ try:
+ self.waitUntilHostInState("Fencing")
+ except Exception as e:
+ self.startAgent()
+ raise Exception("Warning: Exception during test execution : %s" % e)
+
+ # Allow oobm commands to work now
+ self.configureAndEnableOobm()
+
+ # Checks if the host would turn into Fenced
+ try:
+ self.waitUntilHostInState("Fenced")
+ except Exception as e:
+ self.startAgent()
+ raise Exception("Warning: Exception during test execution : %s" % e)
+
+ self.enableAgent()
+ self.startAgent()
+ self.cancelMaintenance()
+ self.waitUntilHostInState("Available")
+
+ def configureAndStartIpmiServer(self, power_state=None):
+ """
+ Setup ipmisim and enable out-of-band management for host
+ """
+ self.configureAndEnableOobm()
+ self.startIpmiServer()
+ if power_state:
+ bmc = IpmiServerContext().bmc
+ bmc.powerstate = power_state
+
+ def assertIssueCommandState(self, command, expected):
+ """
+ Asserts power action result for a given power command
+ """
+ if command != 'STATUS':
+ self.issuePowerActionCmd(command)
+ response = self.issuePowerActionCmd('STATUS')
+ self.assertEqual(response.powerstate, expected)
+
+ def configureAndEnableOobm(self):
+ self.apiclient.configureOutOfBandManagement(self.getOobmConfigCmd())
+ response = self.apiclient.enableOutOfBandManagementForHost(self.getOobmEnableCmd())
+ self.assertEqual(response.enabled, True)
+
+ def startIpmiServer(self):
+ def startIpmiServer(tname, server):
+ self.debug("Starting ipmisim server")
+ try:
+ server.serve_forever()
+ except Exception: pass
+ IpmiServerContext('reset')
+ ThreadedIpmiServer.allow_reuse_address = False
+ server = ThreadedIpmiServer(('0.0.0.0', self.getIpmiServerPort()), IpmiServer)
+ thread.start_new_thread(startIpmiServer, ("ipmi-server", server,))
+ self.server = server
+
+ def stopIpmiServer(self):
+ if self.server:
+ self.server.shutdown()
+ self.server.server_close()
+
+ def getOobmIssueActionCmd(self):
+ cmd = issueOutOfBandManagementPowerAction.issueOutOfBandManagementPowerActionCmd()
+ cmd.hostid = self.host.id
+ cmd.action = 'STATUS'
+ return cmd
+
+ def issuePowerActionCmd(self, action, timeout=None):
+ cmd = self.getOobmIssueActionCmd()
+ cmd.action = action
+ if timeout:
+ cmd.timeout = timeout
+
+ try:
+ return self.apiclient.issueOutOfBandManagementPowerAction(cmd)
+ except Exception as e:
+ if "packet session id 0x0 does not match active session" in str(e):
+ raise self.skipTest("Known ipmitool issue hit, skipping test")
+ raise e
+
+ def getOobmEnableCmd(self):
+ cmd = enableOutOfBandManagementForHost.enableOutOfBandManagementForHostCmd()
+ cmd.hostid = self.host.id
+ return cmd
+
+ def getOobmDisableCmd(self):
+ cmd = disableOutOfBandManagementForHost.disableOutOfBandManagementForHostCmd()
+ cmd.hostid = self.host.id
+ return cmd
+
+ def getIpmiServerPort(self):
+ return self.serverPort
+
+ def getOobmConfigCmd(self):
+ cmd = configureOutOfBandManagement.configureOutOfBandManagementCmd()
+ cmd.driver = 'ipmitool' # The default available driver
+ cmd.address = self.getIpmiServerIp()
+ cmd.port = self.getIpmiServerPort()
+ cmd.username = 'admin'
+ cmd.password = 'password'
+ cmd.hostid = self.host.id
+ return cmd
+
+ def getIpmiServerIp(self):
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ s.connect((self.mgtSvrDetails["mgtSvrIp"], self.mgtSvrDetails["port"]))
+ return s.getsockname()[0]
+
+ def get_non_configured_ha_host(self):
+
+ response = list_hosts(
+ self.apiclient,
+ type='Routing'
+ )
+
+ for host in response:
+ if host.haprovider is None:
+ return host
+ else:
+ cloudstackTestCase.skipTest(self, "There is no non configured hosts. Skipping test.")
+
+ raise self.skipTest("No KVM hosts found, skipping host-ha test")
+
+ def getHAState(self, id):
+ cmd = listHostHAResources.listHostHAResourcesCmd()
+ cmd.hostid = id
+ response = self.apiclient.listHostHAResources(cmd)
+
+ return response[0]
+
+ def startAgent(self):
+ SshClient(host=self.host.ipaddress, port=22, user=self.hostConfig["username"],
+ passwd=self.hostConfig["password"]).execute \
+ ("systemctl start cloudstack-agent || service cloudstack-agent start")
+
+ def stopAgent(self):
+ SshClient(host=self.host.ipaddress, port=22, user=self.hostConfig["username"],
+ passwd=self.hostConfig["password"]).execute \
+ ("systemctl stop cloudstack-agent || service cloudstack-agent stop")
+
+ def killAgent(self):
+ SshClient(host=self.host.ipaddress, port=22, user=self.hostConfig["username"], passwd=self.hostConfig["password"]).execute\
+ ("kill -9 $(ps aux | grep 'cloudstack-agent' | awk '{print $2}')")
+
+ def disableHost(self, id):
+ cmd = updateHost.updateHostCmd()
+ cmd.id = id
+ cmd.allocationstate = "Disable"
+ response = self.apiclient.updateHost(cmd)
+ self.assertEqual(response.resourcestate, "Disabled")
+
+ def enableHost(self, id):
+ cmd = updateHost.updateHostCmd()
+ cmd.id = id
+ cmd.allocationstate = "Enable"
+ response = self.apiclient.updateHost(cmd)
+ self.assertEqual(response.resourcestate, "Enabled")
+
+ def setHostToMaintanance(self, id):
+ cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd()
+ cmd.id = id
+
+ response = self.apiclient.prepareHostForMaintenance(cmd)
+
+ self.assertEqual(response.resourcestate, "PrepareForMaintenance")
+
+ def cancelMaintenance(self):
+ cmd = cancelHostMaintenance.cancelHostMaintenanceCmd()
+ cmd.id = self.host.id
+ response = self.apiclient.cancelHostMaintenance(cmd)
+
+ self.assertEqual(response.resourcestate, "Enabled")
diff --git a/test/integration/smoke/test_hostha_simulator.py b/test/integration/smoke/test_hostha_simulator.py
new file mode 100644
index 00000000000..bb5fcb97c37
--- /dev/null
+++ b/test/integration/smoke/test_hostha_simulator.py
@@ -0,0 +1,776 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import marvin
+from marvin.cloudstackTestCase import *
+from marvin.cloudstackAPI import *
+from marvin.lib.utils import *
+from marvin.lib.base import *
+from marvin.lib.common import *
+from nose.plugins.attrib import attr
+
+from ipmisim.ipmisim import IpmiServerContext, IpmiServer, ThreadedIpmiServer
+
+import random
+import socket
+import sys
+import thread
+import time
+
+
+class TestHostHA(cloudstackTestCase):
+ """ Test host-ha business logic using Simulator
+ """
+
+ def setUp(self):
+ self.apiclient = self.testClient.getApiClient()
+ self.hypervisor = self.testClient.getHypervisorInfo()
+ self.dbclient = self.testClient.getDbConnection()
+ self.services = self.testClient.getParsedTestDataConfig()
+ self.mgtSvrDetails = self.config.__dict__["mgtSvr"][0].__dict__
+ self.fakeMsId = random.randint(10000, 99999) * random.randint(10, 20)
+ self.host = None
+
+ # Cleanup any existing configs
+ self.dbclient.execute("delete from ha_config where resource_type='Host'")
+
+ # use random port for ipmisim
+ s = socket.socket()
+ s.bind(('', 0))
+ self.serverPort = s.getsockname()[1]
+ s.close()
+
+ # Get a host to run tests against
+ self.host = self.getHost()
+
+ self.cleanup = []
+
+
+ def tearDown(self):
+ try:
+ host = self.getHost()
+ self.configureAndDisableHostHa(host.id)
+ self.host = None
+ self.dbclient.execute("delete from mshost_peer where peer_runid=%s" % self.getFakeMsRunId())
+ self.dbclient.execute("delete from mshost where runid=%s" % self.getFakeMsRunId())
+ self.dbclient.execute("delete from cluster_details where name='resourceHAEnabled'")
+ self.dbclient.execute("delete from data_center_details where name='resourceHAEnabled'")
+ self.dbclient.execute("delete from ha_config where resource_type='Host'")
+ self.dbclient.execute("update host set resource_state='Enabled' where type='Routing' and resource_state='Maintenance'")
+ cleanup_resources(self.apiclient, self.cleanup)
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+
+
+ def getFakeMsId(self):
+ return self.fakeMsId
+
+
+ def getFakeMsRunId(self):
+ return self.fakeMsId * 1000
+
+
+ def getHost(self, hostId=None):
+ if self.host and hostId is None:
+ return self.host
+
+ response = list_hosts(
+ self.apiclient,
+ type='Routing',
+ hypervisor='Simulator',
+ resourcestate='Enabled',
+ id=hostId
+ )
+
+ if response and len(response) > 0:
+ random.shuffle(response)
+ self.host = response[0]
+ return self.host
+ raise self.skipTest("No suitable hosts found, skipping host-ha test")
+
+
+ def getHostHaConfigCmd(self, provider='simulatorhaprovider'):
+ cmd = configureHAForHost.configureHAForHostCmd()
+ cmd.provider = provider
+ cmd.hostid = self.getHost().id
+ return cmd
+
+
+ def getHostHaEnableCmd(self):
+ cmd = enableHAForHost.enableHAForHostCmd()
+ cmd.hostid = self.getHost().id
+ return cmd
+
+
+ def getHostHaDisableCmd(self):
+ cmd = disableHAForHost.disableHAForHostCmd()
+ cmd.hostid = self.getHost().id
+ return cmd
+
+
+ def getListHostHAResources(self):
+ cmd = listHostHAResources.listHostHAResourcesCmd()
+ cmd.hostid = self.getHost().id
+ return cmd
+
+
+ def configureAndEnableHostHa(self, initialize=True):
+ self.apiclient.configureHAForHost(self.getHostHaConfigCmd())
+ response = self.apiclient.enableHAForHost(self.getHostHaEnableCmd())
+ self.assertEqual(response.haenable, True)
+ if initialize:
+ self.configureSimulatorHAProviderState(True, True, True, False)
+
+
+ def configureAndDisableHostHa(self, hostId):
+ self.apiclient.configureHAForHost(self.getHostHaConfigCmd())
+ cmd = self.getHostHaDisableCmd()
+ cmd.hostid = hostId
+ response = self.apiclient.disableHAForHost(cmd)
+ self.assertEqual(response.hostid, cmd.hostid)
+ self.assertEqual(response.haenable, False)
+
+
+ def enableHostHa(self, hostId):
+ cmd = self.getHostHaEnableCmd()
+ cmd.hostid = hostId
+ response = self.apiclient.enableHAForHost(cmd)
+ self.assertEqual(response.hostid, cmd.hostid)
+ self.assertEqual(response.haenable, True)
+
+
+ def configureSimulatorHAProviderState(self, health, activity, recover, fence):
+ cmd = configureSimulatorHAProviderState.configureSimulatorHAProviderStateCmd()
+ cmd.hostid = self.getHost().id
+ cmd.health = health
+ cmd.activity = activity
+ cmd.recover = recover
+ cmd.fence = fence
+ response = self.apiclient.configureSimulatorHAProviderState(cmd)
+ self.assertEqual(response.success, 'true')
+
+
+ def getSimulatorHAStateTransitions(self, hostId):
+ cmd = listSimulatorHAStateTransitions.listSimulatorHAStateTransitionsCmd()
+ cmd.hostid = hostId
+ return self.apiclient.listSimulatorHAStateTransitions(cmd)
+
+
+ def checkSyncToState(self, state, interval=5000):
+ def checkForStateSync(expectedState):
+ response = self.getHost(hostId=self.getHost().id).hostha
+ print("checkForStateSync:: response=%s, expected=%s" % (response, expectedState))
+ return response.hastate == expectedState, None
+
+ sync_interval = 1 + int(interval) / 1000
+ res, _ = wait_until(sync_interval, 100, checkForStateSync, state)
+ if not res:
+ self.fail("Failed to get host.hastate synced to expected state:" + state)
+ response = self.getHost(hostId=self.getHost().id).hostha
+ self.assertEqual(response.hastate, state)
+
+
+ def getNonConfiguredHaHost(self):
+ response = list_hosts(
+ self.apiclient,
+ type='Routing'
+ )
+ for host in response:
+ if host.haprovider is None:
+ return host
+ else:
+ return None
+
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_hostha_enable_feature_without_setting_provider(self):
+ """
+ Tests Enable HA without setting the provider, Exception is thrown
+ """
+ host = self.getNonConfiguredHaHost()
+
+ if host is None:
+ cloudstackTestCase.skipTest(self, "There is no non configured hosts. Skipping test.")
+
+ cmd = self.getHostHaEnableCmd()
+ cmd.hostid = host.id
+
+ try:
+ response = self.apiclient.enableHAForHost(cmd)
+ except Exception:
+ pass
+ else:
+ self.fail("Expected an exception to be thrown, failing")
+
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_ha_list_providers(self):
+ """
+ Tests default ha providers list
+ """
+ cmd = listHostHAProviders.listHostHAProvidersCmd()
+
+ cmd.hypervisor = 'Simulator'
+ response = self.apiclient.listHostHAProviders(cmd)[0]
+ self.assertEqual(response.haprovider, 'SimulatorHAProvider')
+
+ cmd.hypervisor = 'KVM'
+ response = self.apiclient.listHostHAProviders(cmd)[0]
+ self.assertEqual(response.haprovider, 'KVMHAProvider')
+
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_hostha_configure_invalid_provider(self):
+ """
+ Tests host-ha configuration with invalid driver
+ """
+ cmd = self.getHostHaConfigCmd()
+ cmd.provider = 'randomDriverThatDoesNotExist'
+ try:
+ response = self.apiclient.configureHAForHost(cmd)
+ except Exception:
+ pass
+ else:
+ self.fail("Expected an exception to be thrown, failing")
+
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_hostha_configure_default_driver(self):
+ """
+ Tests host-ha configuration with valid data
+ """
+ cmd = self.getHostHaConfigCmd()
+ response = self.apiclient.configureHAForHost(cmd)
+ self.assertEqual(response.hostid, cmd.hostid)
+ self.assertEqual(response.haprovider, cmd.provider.lower())
+
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_ha_enable_feature_invalid(self):
+ """
+ Tests ha feature enable command with invalid options
+ """
+ cmd = self.getHostHaEnableCmd()
+ cmd.hostid = -1
+ try:
+ response = self.apiclient.enableHAForHost(cmd)
+ except Exception:
+ pass
+ else:
+ self.fail("Expected an exception to be thrown, failing")
+ try:
+ cmd = enableHAForCluster.enableHAForClusterCmd()
+ response = self.apiclient.enableHAForCluster(cmd)
+ except Exception:
+ pass
+ else:
+ self.fail("Expected an exception to be thrown, failing")
+ try:
+ cmd = enableHAForZone.enableHAForZoneCmd()
+ response = self.apiclient.enableHAForZone(cmd)
+ except Exception:
+ pass
+ else:
+ self.fail("Expected an exception to be thrown, failing")
+
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_ha_disable_feature_invalid(self):
+ """
+ Tests ha feature disable command with invalid options
+ """
+ cmd = self.getHostHaDisableCmd()
+ cmd.hostid = -1
+ try:
+ response = self.apiclient.disableHAForHost(cmd)
+ except Exception:
+ pass
+ else:
+ self.fail("Expected an exception to be thrown, failing")
+ try:
+ cmd = disableHAForCluster.disableHAForClusterCmd()
+ response = self.apiclient.disableHAForCluster(cmd)
+ except Exception:
+ pass
+ else:
+ self.fail("Expected an exception to be thrown, failing")
+
+ try:
+ cmd = disableHAForZone.disableHAForZoneCmd()
+ response = self.apiclient.disableHAForZone(cmd)
+ except Exception:
+ pass
+ else:
+ self.fail("Expected an exception to be thrown, failing")
+
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_hostha_enable_feature_valid(self):
+ """
+ Tests host-ha enable feature with valid options
+ """
+ self.apiclient.configureHAForHost(self.getHostHaConfigCmd())
+ cmd = self.getHostHaEnableCmd()
+ response = self.apiclient.enableHAForHost(cmd)
+ self.assertEqual(response.hostid, cmd.hostid)
+ self.assertEqual(response.haenable, True)
+
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_hostha_disable_feature_valid(self):
+ """
+ Tests host-ha disable feature with valid options
+ """
+ self.apiclient.configureHAForHost(self.getHostHaConfigCmd())
+ cmd = self.getHostHaDisableCmd()
+ response = self.apiclient.disableHAForHost(cmd)
+ self.assertEqual(response.hostid, cmd.hostid)
+ self.assertEqual(response.haenable, False)
+
+ response = self.getHost(hostId=cmd.hostid).hostha
+ self.assertEqual(response.hastate, 'Disabled')
+
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_ha_configure_enabledisable_across_clusterzones(self):
+ """
+ Tests ha enable/disable feature at cluster and zone level
+ Zone > Cluster > Host
+ """
+ host = self.getHost()
+ self.configureAndEnableHostHa()
+
+ self.checkSyncToState('Available')
+ response = self.getHost(hostId=host.id).hostha
+ self.assertTrue(response.hastate == 'Available')
+
+ # Disable at host level
+ cmd = disableHAForHost.disableHAForHostCmd()
+ cmd.hostid = host.id
+ response = self.apiclient.disableHAForHost(cmd)
+
+ # Disable at cluster level
+ cmd = disableHAForCluster.disableHAForClusterCmd()
+ cmd.clusterid = host.clusterid
+ response = self.apiclient.disableHAForCluster(cmd)
+
+ # Disable at zone level
+ cmd = disableHAForZone.disableHAForZoneCmd()
+ cmd.zoneid = host.zoneid
+ response = self.apiclient.disableHAForZone(cmd)
+
+ # HA state check
+ response = self.getHost(hostId=host.id).hostha
+ self.assertTrue(response.hastate == 'Disabled')
+
+ # Check ha-state check and sync
+ self.dbclient.execute("update ha_config set ha_state='Available' where enabled='1' and resource_type='Host'")
+ self.checkSyncToState('Disabled')
+
+ # Enable at zone level
+ cmd = enableHAForZone.enableHAForZoneCmd()
+ cmd.zoneid = host.zoneid
+ response = self.apiclient.enableHAForZone(cmd)
+
+ # Enable at cluster level
+ cmd = enableHAForCluster.enableHAForClusterCmd()
+ cmd.clusterid = host.clusterid
+ response = self.apiclient.enableHAForCluster(cmd)
+
+ # Enable at host level
+ cmd = enableHAForHost.enableHAForHostCmd()
+ cmd.hostid = host.id
+ response = self.apiclient.enableHAForHost(cmd)
+
+ # Check state sync
+ self.checkSyncToState('Available')
+
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_ha_multiple_mgmt_server_ownership(self):
+ """
+ Tests ha resource ownership expiry across multi-mgmt server
+ """
+ host = self.getHost()
+ self.configureAndDisableHostHa(host.id)
+ self.configureSimulatorHAProviderState(True, True, True, False)
+ self.configureAndEnableHostHa(False)
+
+ cloudstackVersion = Configurations.listCapabilities(self.apiclient).cloudstackversion
+
+ currentMsHosts = []
+ mshosts = self.dbclient.execute(
+ "select msid from mshost where version='%s' and removed is NULL and state='Up'" % (cloudstackVersion))
+ if len(mshosts) > 0:
+ currentMsHosts = map(lambda row: row[0], mshosts)
+
+ # Inject fake ms host
+ self.dbclient.execute(
+ "insert into mshost (msid,runid,name,state,version,service_ip,service_port,last_update) values (%s,%s,'ha-marvin-fakebox', 'Down', '%s', '127.0.0.1', '22', NOW())" % (
+ self.getFakeMsId(), self.getFakeMsRunId(), cloudstackVersion))
+
+ # Pass ownership to the fake ms id
+ self.dbclient.execute(
+ "update ha_config set mgmt_server_id=%d where resource_type='Host' and enabled=1 and provider='simulatorhaprovider'" % self.getFakeMsId())
+
+ pingInterval = float(list_configurations(
+ self.apiclient,
+ name='ping.interval'
+ )[0].value)
+
+ pingTimeout = float(list_configurations(
+ self.apiclient,
+ name='ping.timeout'
+ )[0].value)
+
+ def removeFakeMgmtServer(fakeMsRunId):
+ rows = self.dbclient.execute("select * from mshost_peer where peer_runid=%s" % fakeMsRunId)
+ if len(rows) > 0:
+ self.debug("Mgmt server is now trying to contact the fake mgmt server")
+ self.dbclient.execute("update mshost set removed=now() where runid=%s" % fakeMsRunId)
+ self.dbclient.execute("update mshost_peer set peer_state='Down' where peer_runid=%s" % fakeMsRunId)
+ return True, None
+ return False, None
+
+ def checkHaOwnershipExpiry(fakeMsId):
+ rows = self.dbclient.execute(
+ "select mgmt_server_id from ha_config where resource_type='Host' and enabled=1 and provider='simulatorhaprovider'")
+ if len(rows) > 0 and rows[0][0] != fakeMsId:
+ self.debug("HA resource ownership expired as node was detected to be gone")
+ return True, None
+ return False, None
+
+ retry_interval = 1 + (pingInterval * pingTimeout / 10)
+
+ res, _ = wait_until(retry_interval, 20, removeFakeMgmtServer, self.getFakeMsRunId())
+ if not res:
+ self.fail("Management server failed to turn down or remove fake mgmt server")
+
+ res, _ = wait_until(retry_interval, 100, checkHaOwnershipExpiry, self.getFakeMsId())
+ if not res:
+ self.fail("Management server failed to expire ownership of fenced peer")
+
+ self.debug("Testing ha background sync should claim new ownership")
+ self.checkSyncToState('Available')
+
+ result = self.dbclient.execute(
+ "select mgmt_server_id from ha_config where resource_type='Host' and enabled=1 and provider='simulatorhaprovider'")
+ newOwnerId = result[0][0]
+ self.assertTrue(newOwnerId in currentMsHosts)
+
+
+ def checkFSMTransition(self, transition, event, haState, prevHaState, hasActiviyCounter, hasRecoveryCounter):
+ print("checkFSMTransition:: transition=%s, event=%s, state=%s" % (transition, event, haState))
+ self.assertEqual(transition.event, event)
+ self.assertEqual(transition.hastate, haState)
+ self.assertEqual(transition.prevhastate, prevHaState)
+
+ if hasActiviyCounter is None:
+ pass
+ elif hasActiviyCounter:
+ self.assertTrue(transition.activitycounter > 0)
+ else:
+ self.assertEqual(transition.activitycounter, 0)
+
+ if hasRecoveryCounter is None:
+ pass
+ elif hasRecoveryCounter:
+ self.assertTrue(transition.recoverycounter > 0)
+ else:
+ self.assertEqual(transition.recoverycounter, 0)
+
+
+ def findFSMTransitionToState(self, state, host):
+ transitions = self.getSimulatorHAStateTransitions(host.id)
+ if not transitions:
+ print("findFSMTransition:: no transitions returned")
+ return False, (None, None, None)
+
+ previousTransition = None
+ stateTransition = None
+ nextTransition = None
+ for transition in transitions:
+ if stateTransition:
+ nextTransition = transition
+ break
+ if transition.hastate == state:
+ stateTransition = transition
+ if not stateTransition:
+ previousTransition = transition
+
+ print("findFSMTransition:: prev=%s, cur=%s, next=%s, find state=%s" % (previousTransition, stateTransition, nextTransition, state))
+ if stateTransition:
+ return True, (previousTransition, stateTransition, nextTransition,)
+ return False, (previousTransition, stateTransition, nextTransition,)
+
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_ha_verify_fsm_available(self):
+ """
+ Tests ha FSM transitions for valid healthy host
+ Simulates health check passing
+ """
+
+ host = self.getHost()
+ self.configureAndDisableHostHa(host.id)
+ self.configureSimulatorHAProviderState(True, True, True, False)
+ self.configureAndEnableHostHa(False)
+
+ res, (_, T, _) = wait_until(3, 20, self.findFSMTransitionToState, 'available', host)
+ if not res:
+ self.fail("FSM did not transition to available state")
+
+ self.checkFSMTransition(T, 'enabled', 'available', 'disabled', False, False)
+
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_ha_verify_fsm_degraded(self):
+ """
+ Tests ha FSM transitions leading to degraded state
+ Simulates health check failures with activity checks passing
+ FSM transitions should happen indefinitely between:
+ Available->Suspect<->Checking->Degraded->Available
+ """
+ host = self.getHost()
+ self.configureAndDisableHostHa(host.id)
+ self.configureSimulatorHAProviderState(False, True, True, False)
+ self.configureAndEnableHostHa(False)
+
+ # Initial health check failure
+ res, (_, T, _) = wait_until(3, 50, self.findFSMTransitionToState, 'suspect', host)
+ if not res:
+ self.fail("FSM did not transition to suspect state")
+
+ self.checkFSMTransition(T, 'healthcheckfailed', 'suspect', 'available', False, False)
+
+ # Check transition to Degraded
+ res, (prevT, T, _) = wait_until(3, 100, self.findFSMTransitionToState, 'degraded', host)
+ if not res:
+ self.fail("FSM did not transition to degraded state")
+
+ if prevT:
+ self.checkFSMTransition(prevT, 'performactivitycheck', 'checking', 'suspect', True, False)
+ self.checkFSMTransition(T, 'activitycheckfailureunderthresholdratio', 'degraded', 'checking', True, False)
+
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_ha_verify_fsm_recovering(self):
+ """
+ Tests ha FSM transitions leading to recovering
+ Simulates both health and activity check failures
+ FSM transitions should happen indefinitely between:
+ Available->Suspect<->Checking->Recovering->Recovered<-retry-loop->->Fencing
+ """
+ host = self.getHost()
+ self.configureAndDisableHostHa(host.id)
+ self.configureSimulatorHAProviderState(False, False, True, False)
+ self.configureAndEnableHostHa(False)
+
+ # Initial health check failure
+ res, (_, T, _) = wait_until(3, 50, self.findFSMTransitionToState, 'suspect', host)
+ if not res:
+ self.fail("FSM did not transition to suspect state")
+
+ self.checkFSMTransition(T, 'healthcheckfailed', 'suspect', 'available', False, False)
+
+ # Check transition to recovering
+ res, (prevT, T, _) = wait_until(3, 100, self.findFSMTransitionToState, 'recovering', host)
+ if not res:
+ self.fail("FSM did not transition to recovering state")
+
+ if prevT:
+ self.checkFSMTransition(prevT, 'performactivitycheck', 'checking', 'suspect', True, False)
+ self.checkFSMTransition(T, 'activitycheckfailureoverthresholdratio', 'recovering', 'checking', True, False)
+
+ # Check transition to fencing due to recovery attempts exceeded
+ res, (_, T, _) = wait_until(3, 100, self.findFSMTransitionToState, 'fencing', host)
+ if not res:
+ self.fail("FSM did not transition to fencing state")
+
+ self.checkFSMTransition(T, 'recoveryoperationthresholdexceeded', 'fencing', 'recovering', None, True)
+
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_ha_verify_fsm_fenced(self):
+ """
+ Tests ha FSM transitions for failures leading to fenced state
+ FSM transitions should happen indefinitely between:
+ Available->Suspect<->Checking->Recovering<-fail recovery->->Fencing->Fenced
+ """
+ host = self.getHost()
+ self.configureAndDisableHostHa(host.id)
+ self.configureSimulatorHAProviderState(False, False, False, True)
+ self.configureAndEnableHostHa(False)
+
+ # Check for transition to fenced
+ res, (prevT, T, _) = wait_until(3, 100, self.findFSMTransitionToState, 'fenced', host)
+ if not res:
+ self.fail("FSM did not transition to fenced state")
+
+ self.checkFSMTransition(prevT, 'recoveryoperationthresholdexceeded', 'fencing', 'recovering', False, True)
+ self.checkFSMTransition(T, 'fenced', 'fenced', 'fencing', False, False)
+
+ # Simulate manual recovery of host and cancel maintenance mode
+ self.configureSimulatorHAProviderState(True, True, True, False)
+ cancelCmd = cancelHostMaintenance.cancelHostMaintenanceCmd()
+ cancelCmd.id = host.id
+ self.apiclient.cancelHostMaintenance(cancelCmd)
+
+ # Check for transition to available after manual recovery
+ res, (prevT, T, _) = wait_until(3, 50, self.findFSMTransitionToState, 'available', host)
+ if not res:
+ self.fail("FSM did not transition to available state")
+
+ self.checkFSMTransition(T, 'eligible', 'available', 'ineligible', False, False)
+
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_configure_ha_provider_invalid(self):
+ """
+ Tests configure HA Provider with invalid provider options
+ """
+
+ # Enable ha for host
+ self.apiclient.configureHAForHost(self.getHostHaConfigCmd())
+ cmd = self.getHostHaEnableCmd()
+ response = self.apiclient.enableHAForHost(cmd)
+ self.assertEqual(response.hostid, cmd.hostid)
+ self.assertEqual(response.haenable, True)
+
+ host = self.getHost(response.hostid)
+
+ # Setup wrong configuration for the host
+ conf_ha_cmd = configureHAForHost.configureHAForHostCmd()
+ if host.hypervisor.lower() in "simulator":
+ conf_ha_cmd.provider = "kvmhaprovider"
+ if host.hypervisor.lower() in "kvm":
+ conf_ha_cmd.provider = "simulatorhaprovider"
+
+ conf_ha_cmd.hostid = cmd.hostid
+
+ # Call the configure HA provider API with not supported provider for HA
+ try:
+ self.apiclient.configureHAForHost(conf_ha_cmd)
+ except Exception:
+ pass
+ else:
+ self.fail("Expected an exception to be thrown, failing")
+
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_configure_ha_provider_valid(self):
+ """
+ Tests configure HA Provider with valid provider options
+ """
+
+ # Enable ha for host
+ self.apiclient.configureHAForHost(self.getHostHaConfigCmd())
+ cmd = self.getHostHaEnableCmd()
+ response = self.apiclient.enableHAForHost(cmd)
+ self.assertEqual(response.hostid, cmd.hostid)
+ self.assertEqual(response.haenable, True)
+
+ host = self.getHost(response.hostid)
+
+
+ # Setup wrong configuration for the host
+ conf_ha_cmd = configureHAForHost.configureHAForHostCmd()
+ if host.hypervisor.lower() in "kvm":
+ conf_ha_cmd.provider = "kvmhaprovider"
+ if host.hypervisor.lower() in "simulator":
+ conf_ha_cmd.provider = "simulatorhaprovider"
+
+ conf_ha_cmd.hostid = cmd.hostid
+
+ # Call the configure HA provider API with not supported provider for HA
+ response = self.apiclient.configureHAForHost(conf_ha_cmd)
+
+ # Check the response contains the set provider and hostID
+ self.assertEqual(response.haprovider, conf_ha_cmd.provider)
+ self.assertEqual(response.hostid, conf_ha_cmd.hostid)
+
+
+ def getHaProvider(self, host):
+ cmd = listHostHAProviders.listHostHAProvidersCmd()
+ cmd.hypervisor = host.hypervisor
+ response = self.apiclient.listHostHAProviders(cmd)
+ return response[0].haprovider
+
+
+ def configureHaProvider(self):
+ cmd = self.getHostHaConfigCmd(self.getHaProvider(self.getHost()))
+ return self.apiclient.configureHAForHost(cmd)
+
+
+ @attr(tags=["advanced",
+ "advancedns",
+ "smoke",
+ "basic",
+ "sg"],
+ required_hardware="false")
+ def test_list_ha_for_host(self):
+ """
+ Test that verifies the listHAForHost API
+ """
+ self.configureHaProvider()
+ db_count = self.dbclient.execute("SELECT count(*) FROM cloud.ha_config")
+
+ cmd = self.getListHostHAResources()
+ del cmd.hostid
+ response = self.apiclient.listHostHAResources(cmd)
+
+ self.assertEqual(db_count[0][0], len(response))
+
+
+ @attr(tags=["advanced",
+ "advancedns",
+ "smoke",
+ "basic",
+ "sg"],
+ required_hardware="false")
+ def test_list_ha_for_host_valid(self):
+ """
+ Valid test for listing a specific host HA resources
+ """
+
+ self.configureHaProvider()
+ cmd = self.getListHostHAResources()
+ response = self.apiclient.listHostHAResources(cmd)
+ self.assertEqual(response[0].hostid, cmd.hostid)
+
+
+ @attr(tags=["advanced",
+ "advancedns",
+ "smoke",
+ "basic",
+ "sg"],
+ required_hardware="false")
+ def test_list_ha_for_host_invalid(self):
+ """
+ Test that listHostHAResources is returning exception when called with invalid data
+ """
+
+ self.configureHaProvider()
+ cmd = self.getListHostHAResources()
+ cmd.hostid = "someinvalidvalue"
+
+ try:
+ response = self.apiclient.listHostHAResources(cmd)
+ except Exception:
+ pass
+ else:
+ self.fail("Expected an exception to be thrown, failing")
diff --git a/test/integration/smoke/test_iso.py b/test/integration/smoke/test_iso.py
index 9bad575b8d0..afd540a4624 100755
--- a/test/integration/smoke/test_iso.py
+++ b/test/integration/smoke/test_iso.py
@@ -17,8 +17,10 @@
""" BVT tests for Templates ISO
"""
# Import Local Modules
+from marvin.cloudstackException import GetDetailExceptionInfo
from marvin.cloudstackTestCase import cloudstackTestCase, unittest
-from marvin.cloudstackAPI import listZones, updateIso, extractIso, updateIsoPermissions, copyIso, deleteIso
+from marvin.cloudstackAPI import listZones, updateIso, extractIso, updateIsoPermissions, copyIso, deleteIso,\
+ registerIso,listOsTypes
from marvin.lib.utils import cleanup_resources, random_gen, get_hypervisor_type,validateList
from marvin.lib.base import Account, Iso
from marvin.lib.common import (get_domain,
@@ -320,8 +322,8 @@ def test_02_edit_iso(self):
"Check display text of updated ISO"
)
self.assertEqual(
- iso_response.bootable,
- self.services["bootable"],
+ str(iso_response.bootable).lower(),
+ str(self.services["bootable"]).lower(),
"Check if image is bootable of updated ISO"
)
@@ -473,14 +475,14 @@ def test_05_iso_permissions(self):
"Check ISO ID"
)
self.assertEqual(
- iso_response.ispublic,
- self.services["ispublic"],
+ str(iso_response.ispublic).lower(),
+ str(self.services["ispublic"]).lower(),
"Check ispublic permission of ISO"
)
self.assertEqual(
- iso_response.isfeatured,
- self.services["isfeatured"],
+ str(iso_response.isfeatured).lower(),
+ str(self.services["isfeatured"]).lower(),
"Check isfeatured permission of ISO"
)
return
@@ -606,3 +608,165 @@ def test_07_list_default_iso(self):
self.get_iso_details("vmware-tools.iso")
self.get_iso_details("xs-tools.iso")
return
+
+
+class TestCreateISOWithChecksum(cloudstackTestCase):
+ def setUp(self):
+ self.testClient = super(TestCreateISOWithChecksum, self).getClsTestClient()
+ self.apiclient = self.testClient.getApiClient()
+ self.cleanup = []
+
+ self.unsupportedHypervisor = False
+ self.hypervisor = self.testClient.getHypervisorInfo()
+ if self.hypervisor.lower() in ['lxc']:
+ # Template creation from root volume is not supported in LXC
+ self.unsupportedHypervisor = True
+ return
+
+ # Get Zone, Domain and templates
+ self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests())
+
+ # Setup default create iso attributes
+ self.iso = registerIso.registerIsoCmd()
+ self.iso.checksum = "{SHA-1}" + "e16f703b5d6cb6dd2c448d956be63fcbee7d79ea"
+ self.iso.zoneid = self.zone.id
+ self.iso.name = 'test-tynyCore-iso'
+ self.iso.displaytext = 'test-tynyCore-iso'
+ self.iso.url = "http://dl.openvm.eu/cloudstack/iso/TinyCore-8.0.iso"
+ self.iso.ostypeid = self.getOsType("Other Linux (64-bit)")
+ self.md5 = "f7fee34a73a7f8e3adb30778c7c32c51"
+ self.sha256 = "069a22f7cc15b34cd39f6dd61ef0cf99ff47a1a92942772c30f50988746517f7"
+
+ if self.unsupportedHypervisor:
+ self.skipTest("Skipping test because unsupported hypervisor\
+ %s" % self.hypervisor)
+ return
+
+ def tearDown(self):
+ try:
+ # Clean up the created templates
+ for temp in self.cleanup:
+ cmd = deleteIso.deleteIsoCmd()
+ cmd.id = temp.id
+ cmd.zoneid = self.zone.id
+ self.apiclient.deleteIso(cmd)
+
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+ return
+
+ @attr(tags=["advanced", "smoke"], required_hardware="true")
+ def test_01_create_iso_with_checksum_sha1(self):
+ iso = self.registerIso(self.iso)
+ self.download(self.apiclient, iso.id)
+
+ @attr(tags=["advanced", "smoke"], required_hardware="true")
+ def test_02_create_iso_with_checksum_sha256(self):
+ self.iso.checksum = "{SHA-256}" + self.sha256
+ iso = self.registerIso(self.iso)
+ self.download(self.apiclient, iso.id)
+
+ @attr(tags=["advanced", "smoke"], required_hardware="true")
+ def test_03_create_iso_with_checksum_md5(self):
+ self.iso.checksum = "{md5}" + self.md5
+ iso = self.registerIso(self.iso)
+ self.download(self.apiclient, iso.id)
+
+ @attr(tags=["advanced", "smoke"], required_hardware="true")
+ def test_01_1_create_iso_with_checksum_sha1_negative(self):
+ self.iso.checksum = "{sha-1}" + "someInvalidValue"
+ iso = self.registerIso(self.iso)
+
+ try:
+ self.download(self.apiclient, iso.id)
+ except Exception as e:
+ print "Negative Test Passed - Exception Occurred Under iso download " \
+ "%s" % GetDetailExceptionInfo(e)
+ else:
+ self.fail("Negative Test Failed - Exception DID NOT Occurred Under iso download ")
+
+ @attr(tags=["advanced", "smoke"], required_hardware="true")
+ def test_02_1_create_iso_with_checksum_sha256_negative(self):
+ self.iso.checksum = "{SHA-256}" + "someInvalidValue"
+ iso = self.registerIso(self.iso)
+
+ try:
+ self.download(self.apiclient, iso.id)
+ except Exception as e:
+ print "Negative Test Passed - Exception Occurred Under iso download " \
+ "%s" % GetDetailExceptionInfo(e)
+ else:
+ self.fail("Negative Test Failed - Exception DID NOT Occurred Under iso download ")
+
+ @attr(tags=["advanced", "smoke"], required_hardware="true")
+ def test_03_1_create_iso_with_checksum_md5_negative(self):
+ self.iso.checksum = "{md5}" + "someInvalidValue"
+ iso = self.registerIso(self.iso)
+
+ try:
+ self.download(self.apiclient, iso.id)
+ except Exception as e:
+ print "Negative Test Passed - Exception Occurred Under iso download " \
+ "%s" % GetDetailExceptionInfo(e)
+ else:
+ self.fail("Negative Test Failed - Exception DID NOT Occurred Under iso download ")
+
+ @attr(tags=["advanced", "smoke"], required_hardware="true")
+ def test_04_create_iso_with_no_checksum(self):
+ self.iso.checksum = None
+ iso = self.registerIso(self.iso)
+ self.download(self.apiclient, iso.id)
+
+ def registerIso(self, cmd):
+ iso = self.apiclient.registerIso(cmd)[0]
+ self.cleanup.append(iso)
+ return iso
+
+ def getOsType(self, param):
+ cmd = listOsTypes.listOsTypesCmd()
+ cmd.description = param
+ return self.apiclient.listOsTypes(cmd)[0].id
+
+ def download(self, apiclient, iso_id, retries=12, interval=5):
+ """Check if template download will finish in 1 minute"""
+ while retries > -1:
+ time.sleep(interval)
+ iso_response = Iso.list(
+ apiclient,
+ id=iso_id
+ )
+
+ if isinstance(iso_response, list):
+ iso = iso_response[0]
+ if not hasattr(iso, 'status') or not iso or not iso.status:
+ retries = retries - 1
+ continue
+
+ # If iso is ready,
+ # iso.status = Download Complete
+ # Downloading - x% Downloaded
+ # if Failed
+ # Error - Any other string
+ if 'Failed' in iso.status:
+ raise Exception(
+ "Failed to download iso: status - %s" %
+ iso.status)
+
+ elif iso.status == 'Successfully Installed' and iso.isready:
+ return
+
+ elif 'Downloaded' in iso.status:
+ retries = retries - 1
+ continue
+
+ elif 'Installing' not in iso.status:
+ if retries >= 0:
+ retries = retries - 1
+ continue
+ raise Exception(
+ "Error in downloading iso: status - %s" %
+ iso.status)
+
+ else:
+ retries = retries - 1
+ raise Exception("Template download failed exception.")
\ No newline at end of file
diff --git a/test/integration/smoke/test_nic.py b/test/integration/smoke/test_nic.py
index 7067074c78b..c7f8468d7f2 100644
--- a/test/integration/smoke/test_nic.py
+++ b/test/integration/smoke/test_nic.py
@@ -30,13 +30,21 @@
import signal
import sys
+import logging
import time
+import threading
+import Queue
class TestNic(cloudstackTestCase):
def setUp(self):
self.cleanup = []
+ self.logger = logging.getLogger('TestNIC')
+ self.stream_handler = logging.StreamHandler()
+ self.logger.setLevel(logging.DEBUG)
+ self.logger.addHandler(self.stream_handler)
+
def signal_handler(signal, frame):
self.tearDown()
@@ -278,6 +286,173 @@ def test_01_nic(self):
return
+ def test_02_nic_with_mac(self):
+ """Test to add and update added nic to a virtual machine with specific mac"""
+
+ hypervisorIsVmware = False
+ isVmwareToolInstalled = False
+ if self.hypervisor.lower() == "vmware":
+ hypervisorIsVmware = True
+
+ self.virtual_machine2 = VirtualMachine.create(
+ self.apiclient,
+ self.services["small"],
+ accountid=self.account.name,
+ domainid=self.account.domainid,
+ serviceofferingid=self.service_offering.id,
+ networkids=[self.test_network.id],
+ macaddress="aa:bb:cc:dd:ee:ff",
+ mode=self.zone.networktype if hypervisorIsVmware else "default"
+ )
+ self.cleanup.insert(0, self.virtual_machine2)
+ self.assertEqual(self.virtual_machine2.nic[0].macaddress, "aa:bb:cc:dd:ee:ff", "Mac address not honored")
+ vmdata = self.virtual_machine2.add_nic(
+ self.apiclient,
+ self.test_network2.id,
+ macaddress="ee:ee:dd:cc:bb:aa")
+ found = False
+ for n in vmdata.nic:
+ if n.macaddress == "ee:ee:dd:cc:bb:aa":
+ found = True
+ break
+
+ self.assertTrue(found, "Nic not successfully added with specified mac address")
+
+
+ @attr(tags = ["devcloud", "advanced", "advancedns", "smoke"], required_hardware="true")
+ def test_03_nic_multiple_vmware(self):
+ """Test to adding multiple nics to a VMware VM and restarting VM
+
+ Refer to CLOUDSTACK-10107 for details, in this test we add 8 nics to
+ a VM and stop, start it to show that VMware VMs are not limited to
+ having up to 7 nics.
+ """
+
+ if self.hypervisor.lower() != "vmware":
+ self.skipTest("Skipping test applicable for VMware")
+
+ network_offering = NetworkOffering.create(
+ self.apiclient,
+ self.services["nw_off_isolated_persistent"]
+ )
+ self.cleanup.insert(0, network_offering)
+ network_offering.update(self.apiclient, state='Enabled')
+
+ offering = dict(self.services["network"])
+ offering["networkoffering"] = network_offering.id
+
+ networks = []
+
+ def createNetwork(idx):
+ offering["name"] = "Test Network%s" % idx
+ network = Network.create(
+ self.apiclient,
+ offering,
+ self.account.name,
+ self.account.domainid,
+ zoneid=self.services["network"]["zoneid"]
+ )
+ networks.append(network)
+ self.cleanup.insert(0, network)
+
+
+ class NetworkMaker(threading.Thread):
+ def __init__(self, queue=None, createNetwork=None):
+ threading.Thread.__init__(self)
+ self.queue = queue
+ self.createNetwork = createNetwork
+
+ def run(self):
+ while True:
+ idx = self.queue.get()
+ if idx is not None:
+ self.createNetwork(idx)
+ self.queue.task_done()
+
+ # Start multiple networks
+ tsize = 8
+ queue = Queue.Queue()
+ for _ in range(tsize):
+ worker = NetworkMaker(queue, createNetwork)
+ worker.setDaemon(True)
+ worker.start()
+
+ for idx in range(tsize):
+ queue.put(idx)
+ queue.join()
+
+ # Deploy a VM
+ vm = VirtualMachine.create(
+ self.apiclient,
+ self.services["small"],
+ accountid=self.account.name,
+ domainid=self.account.domainid,
+ serviceofferingid=self.service_offering.id,
+ networkids=[networks[0].id],
+ mode=self.zone.networktype
+ )
+ self.cleanup.insert(0, vm)
+
+ # Add nics to networks
+ for network in networks[1:]:
+ response = vm.add_nic(self.apiclient, network.id)
+ found = False
+ for nic in response.nic:
+ if nic.networkid == network.id:
+ found = True
+ break
+ self.assertTrue(found, "Nic not successfully added for the specific network")
+
+ # Stop VM
+ vm.stop(self.apiclient, forced=True)
+
+ vms = VirtualMachine.list(
+ self.apiclient,
+ id=vm.id
+ )
+ self.assertEqual(
+ validateList(vms)[0],
+ PASS,
+ "vms list validation failed")
+
+ vm_response = vms[0]
+ self.assertEqual(
+ vm_response.state,
+ "Stopped",
+ "Verify the VM is stopped"
+ )
+
+ # Start VM
+ vm.start(self.apiclient)
+
+ vms = VirtualMachine.list(
+ self.apiclient,
+ id=vm.id
+ )
+ self.assertEqual(
+ validateList(vms)[0],
+ PASS,
+ "vms list validation failed")
+
+ vm_response = vms[0]
+ self.assertEqual(
+ vm_response.state,
+ "Running",
+ "Verify the VM is running"
+ )
+
+ self.assertTrue(len(vm_response.nic) == len(networks), "Number of nics on VM not 8")
+
+ # Validate nics exist on each of the network
+ for network in networks:
+ found = False
+ for nic in vm_response.nic:
+ if nic.networkid == network.id:
+ found = True
+ break
+ self.assertTrue(found, "Nic not found for the specific network")
+
+
def tearDown(self):
try:
for obj in self.cleanup:
diff --git a/test/integration/smoke/test_outofbandmanagement.py b/test/integration/smoke/test_outofbandmanagement.py
index e91d49a91b0..a52e3b1f643 100644
--- a/test/integration/smoke/test_outofbandmanagement.py
+++ b/test/integration/smoke/test_outofbandmanagement.py
@@ -211,8 +211,10 @@ def test_oobm_configure_invalid_driver(self):
cmd.driver = 'randomDriverThatDoesNotExist'
try:
response = self.apiclient.configureOutOfBandManagement(cmd)
+ except Exception:
+ pass
+ else:
self.fail("Expected an exception to be thrown, failing")
- except Exception: pass
@attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
@@ -239,20 +241,26 @@ def test_oobm_enable_feature_invalid(self):
cmd.hostid = -1
try:
response = self.apiclient.enableOutOfBandManagementForHost(cmd)
+ except Exception:
+ pass
+ else:
self.fail("Expected an exception to be thrown, failing")
- except Exception: pass
try:
cmd = enableOutOfBandManagementForCluster.enableOutOfBandManagementForClusterCmd()
response = self.apiclient.enableOutOfBandManagementForCluster(cmd)
+ except Exception:
+ pass
+ else:
self.fail("Expected an exception to be thrown, failing")
- except Exception: pass
try:
cmd = enableOutOfBandManagementForZone.enableOutOfBandManagementForZoneCmd()
response = self.apiclient.enableOutOfBandManagementForZone(cmd)
+ except Exception:
+ pass
+ else:
self.fail("Expected an exception to be thrown, failing")
- except Exception: pass
@attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
@@ -265,20 +273,26 @@ def test_oobm_disable_feature_invalid(self):
cmd.hostid = -1
try:
response = self.apiclient.disableOutOfBandManagementForHost(cmd)
+ except Exception:
+ pass
+ else:
self.fail("Expected an exception to be thrown, failing")
- except Exception: pass
try:
cmd = disableOutOfBandManagementForCluster.disableOutOfBandManagementForClusterCmd()
response = self.apiclient.disableOutOfBandManagementForCluster(cmd)
+ except Exception:
+ pass
+ else:
self.fail("Expected an exception to be thrown, failing")
- except Exception: pass
try:
cmd = disableOutOfBandManagementForZone.disableOutOfBandManagementForZoneCmd()
response = self.apiclient.disableOutOfBandManagementForZone(cmd)
+ except Exception:
+ pass
+ else:
self.fail("Expected an exception to be thrown, failing")
- except Exception: pass
@attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
@@ -340,8 +354,10 @@ def test_oobm_enabledisable_across_clusterzones(self):
try:
self.issuePowerActionCmd('STATUS')
- self.fail("Exception was expected, oobm is disabled at zone level")
- except Exception: pass
+ except Exception:
+ pass
+ else:
+ self.fail("Expected an exception to be thrown, failing")
# Enable at zone level
cmd = enableOutOfBandManagementForZone.enableOutOfBandManagementForZoneCmd()
@@ -350,18 +366,16 @@ def test_oobm_enabledisable_across_clusterzones(self):
try:
self.issuePowerActionCmd('STATUS')
- self.fail("Exception was expected, oobm is disabled at cluster level")
- except Exception: pass
+ except Exception:
+ pass
+ else:
+ self.fail("Expected an exception to be thrown, failing")
# Check background thread syncs state to Disabled
response = self.getHost(hostId=host.id).outofbandmanagement
self.assertEqual(response.powerstate, 'Disabled')
self.dbclient.execute("update oobm set power_state='On' where port=%d" % self.getIpmiServerPort())
- interval = list_configurations(
- self.apiclient,
- name='outofbandmanagement.sync.interval'
- )[0].value
- self.checkSyncToState('Disabled', interval)
+ self.checkSyncToState('Disabled', 2)
# Enable at cluster level
cmd = enableOutOfBandManagementForCluster.enableOutOfBandManagementForClusterCmd()
@@ -370,8 +384,10 @@ def test_oobm_enabledisable_across_clusterzones(self):
try:
self.issuePowerActionCmd('STATUS')
- self.fail("Exception was expected, oobm is disabled at host level")
- except Exception: pass
+ except Exception:
+ pass
+ else:
+ self.fail("Expected an exception to be thrown, failing")
# Enable at host level
cmd = enableOutOfBandManagementForHost.enableOutOfBandManagementForHostCmd()
@@ -452,25 +468,21 @@ def test_oobm_background_powerstate_sync(self):
Tests out-of-band management background powerstate sync
"""
self.debug("Testing oobm background sync")
- interval = list_configurations(
- self.apiclient,
- name='outofbandmanagement.sync.interval'
- )[0].value
self.configureAndEnableOobm()
bmc = IpmiServerContext().bmc
bmc.powerstate = 'on'
- self.checkSyncToState('On', interval)
+ self.checkSyncToState('On', 2)
bmc.powerstate = 'off'
- self.checkSyncToState('Off', interval)
+ self.checkSyncToState('Off', 2)
# Check for unknown state (ipmi server not reachable)
cmd = self.getOobmConfigCmd()
cmd.port = 1
response = self.apiclient.configureOutOfBandManagement(cmd)
- self.checkSyncToState('Unknown', interval)
+ self.checkSyncToState('Unknown', 2)
@attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
@@ -532,15 +544,11 @@ def checkOobmOwnershipExpiry(serverPort, fakeMsId):
self.fail("Management server failed to expire ownership of fenced peer")
self.debug("Testing oobm background sync should claim new ownership")
- interval = list_configurations(
- self.apiclient,
- name='outofbandmanagement.sync.interval'
- )[0].value
bmc = IpmiServerContext().bmc
bmc.powerstate = 'on'
- self.checkSyncToState('On', interval)
+ self.checkSyncToState('On', 2)
result = self.dbclient.execute("select mgmt_server_id from oobm where port=%d" % (self.getIpmiServerPort()))
newOwnerId = result[0][0]
@@ -585,8 +593,10 @@ def test_oobm_zchange_password(self):
try:
response = self.issuePowerActionCmd('STATUS')
+ except Exception:
+ pass
+ else:
self.fail("Expected an exception to be thrown, failing")
- except Exception: pass
alerts = Alert.list(self.apiclient, keyword="auth-error",
listall=True)
diff --git a/test/integration/smoke/test_outofbandmanagement_nestedplugin.py b/test/integration/smoke/test_outofbandmanagement_nestedplugin.py
new file mode 100644
index 00000000000..13fb9dd0b85
--- /dev/null
+++ b/test/integration/smoke/test_outofbandmanagement_nestedplugin.py
@@ -0,0 +1,256 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import marvin
+from marvin.cloudstackTestCase import *
+from marvin.cloudstackAPI import *
+from marvin.lib.utils import *
+from marvin.lib.base import *
+from marvin.lib.common import *
+from nose.plugins.attrib import attr
+
+from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
+
+import socket
+import sys
+import thread
+import time
+
+
+apiRequests = []
+state = "Running"
+
+
+class MockedCloudStackServer(BaseHTTPRequestHandler):
+ """
+ Mocked ACS Mgmt Server
+ """
+ def do_GET(self):
+ global apiRequests, state
+ command = self.path.split('command=')[1].split('&')[0]
+ if command == 'startVirtualMachine':
+ state = "Running"
+ elif command == 'stopVirtualMachine':
+ state = "Stopped"
+ elif command == 'rebootVirtualMachine':
+ state = "Running"
+
+ apiRequests.append(command)
+
+ self.send_response(200)
+ self.send_header('Content-type','application/json')
+ self.end_headers()
+
+ json = "{\"listvirtualmachinesresponse\":{\"count\":1,\"virtualmachine\":[{\"id\":\"some-uuid\",\"name\":\"test-vm\",\"state\":\"%s\"}]}}" % state
+ self.wfile.write(json)
+
+ def log_message(self, format, *args):
+ return
+
+
+class TestOutOfBandManagement(cloudstackTestCase):
+ """ Test cases for out of band management
+ """
+
+ def setUp(self):
+ self.apiclient = self.testClient.getApiClient()
+ self.hypervisor = self.testClient.getHypervisorInfo()
+ self.dbclient = self.testClient.getDbConnection()
+ self.services = self.testClient.getParsedTestDataConfig()
+ self.mgtSvrDetails = self.config.__dict__["mgtSvr"][0].__dict__
+
+ self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests())
+ self.host = None
+ self.server = None
+
+ # use random port for mocked-mgmt server
+ s = socket.socket()
+ s.bind(('', 0))
+ self.serverPort = s.getsockname()[1]
+ s.close()
+
+ self.cleanup = []
+ global state, apiRequests
+ state = "Running"
+ apiRequests = []
+
+
+ def tearDown(self):
+ try:
+ self.dbclient.execute("delete from oobm where driver='nestedcloudstack' and port='some-uuid'")
+ cleanup_resources(self.apiclient, self.cleanup)
+ if self.server:
+ self.server.socket.close()
+ global apiRequests
+ apiRequests = []
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+
+
+ def getHost(self, hostId=None):
+ if self.host and hostId is None:
+ return self.host
+
+ response = list_hosts(
+ self.apiclient,
+ zoneid=self.zone.id,
+ type='Routing',
+ id=hostId)
+ if len(response) > 0:
+ self.host = response[0]
+ return self.host
+ raise self.skipTest("No hosts found, skipping out-of-band management test")
+
+
+ def getServerIp(self):
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.connect((self.mgtSvrDetails["mgtSvrIp"], self.mgtSvrDetails["port"]))
+ return s.getsockname()[0]
+
+
+ def getServerPort(self):
+ return self.serverPort
+
+
+ def getOobmConfigCmd(self):
+ cmd = configureOutOfBandManagement.configureOutOfBandManagementCmd()
+ cmd.driver = 'nestedcloudstack'
+ cmd.address = 'http://%s:%s/client/api' % (self.getServerIp(), self.getServerPort())
+ cmd.port = 'some-uuid'
+ cmd.username = 'admin'
+ cmd.password = 'password'
+ cmd.hostid = self.getHost().id
+ return cmd
+
+
+ def getOobmEnableCmd(self):
+ cmd = enableOutOfBandManagementForHost.enableOutOfBandManagementForHostCmd()
+ cmd.hostid = self.getHost().id
+ return cmd
+
+
+ def getOobmIssueActionCmd(self):
+ cmd = issueOutOfBandManagementPowerAction.issueOutOfBandManagementPowerActionCmd()
+ cmd.hostid = self.getHost().id
+ cmd.action = 'STATUS'
+ return cmd
+
+
+ def issuePowerActionCmd(self, action):
+ cmd = self.getOobmIssueActionCmd()
+ cmd.action = action
+ return self.apiclient.issueOutOfBandManagementPowerAction(cmd)
+
+
+ def configureAndEnableOobm(self):
+ self.apiclient.configureOutOfBandManagement(self.getOobmConfigCmd())
+ response = self.apiclient.enableOutOfBandManagementForHost(self.getOobmEnableCmd())
+ self.assertEqual(response.enabled, True)
+
+
+ def startMgmtServer(self):
+ def startMgmtServer(tname, server):
+ self.debug("Starting ACS mocked-mgmt server")
+ try:
+ server.serve_forever()
+ except Exception: pass
+ server = HTTPServer(('0.0.0.0', self.getServerPort()), MockedCloudStackServer)
+ thread.start_new_thread(startMgmtServer, ("mocked-mgmt-server", server,))
+ self.server = server
+
+
+ def configureAndStartMgmtServer(self):
+ """
+ Configure mocked-mgmt server and enable out-of-band management for host
+ """
+ self.configureAndEnableOobm()
+ self.startMgmtServer()
+
+
+ def assertIssueCommandState(self, command, expected):
+ """
+ Asserts power action result for a given power command
+ """
+
+ if command != 'STATUS':
+ self.issuePowerActionCmd(command)
+ response = self.issuePowerActionCmd('STATUS')
+ self.assertEqual(response.powerstate, expected)
+
+
+ @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_oobm_issue_power_status(self):
+ """
+ Tests out-of-band management issue power action
+ """
+ self.configureAndStartMgmtServer()
+ self.assertIssueCommandState('STATUS', 'On')
+
+
+ @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_oobm_issue_power_on(self):
+ """
+ Tests out-of-band management issue power on action
+ """
+ self.configureAndStartMgmtServer()
+ self.assertIssueCommandState('ON', 'On')
+ global apiRequests
+ self.assertTrue('startVirtualMachine' in apiRequests)
+
+
+ @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_oobm_issue_power_off(self):
+ """
+ Tests out-of-band management issue power off action
+ """
+ self.configureAndStartMgmtServer()
+ self.assertIssueCommandState('OFF', 'Off')
+ global apiRequests
+ self.assertTrue('stopVirtualMachine' in apiRequests)
+
+
+ @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_oobm_issue_power_cycle(self):
+ """
+ Tests out-of-band management issue power cycle action
+ """
+ self.configureAndStartMgmtServer()
+ self.assertIssueCommandState('CYCLE', 'On')
+ global apiRequests
+ self.assertTrue('rebootVirtualMachine' in apiRequests)
+
+
+ @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_oobm_issue_power_reset(self):
+ """
+ Tests out-of-band management issue power reset action
+ """
+ self.configureAndStartMgmtServer()
+ self.assertIssueCommandState('RESET', 'On')
+ global apiRequests
+ self.assertTrue('rebootVirtualMachine' in apiRequests)
+
+
+ @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_oobm_issue_power_soft(self):
+ """
+ Tests out-of-band management issue power soft action
+ """
+ self.configureAndStartMgmtServer()
+ self.assertIssueCommandState('SOFT', 'Off')
+ global apiRequests
+ self.assertTrue('stopVirtualMachine' in apiRequests)
diff --git a/test/integration/smoke/test_portforwardingrules.py b/test/integration/smoke/test_portforwardingrules.py
new file mode 100644
index 00000000000..fbac0b442d3
--- /dev/null
+++ b/test/integration/smoke/test_portforwardingrules.py
@@ -0,0 +1,428 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Import Local Modules
+from marvin.cloudstackTestCase import cloudstackTestCase, unittest
+from marvin.lib.base import (PublicIPAddress,
+ NetworkOffering,
+ Autoscale,
+ Network,
+ NetworkServiceProvider,
+ Template,
+ VirtualMachine,
+ VPC,
+ VpcOffering,
+ StaticNATRule,
+ FireWallRule,
+ NATRule,
+ Vpn,
+ VpnUser,
+ LoadBalancerRule,
+ Account,
+ ServiceOffering,
+ PhysicalNetwork,
+ User)
+from marvin.lib.common import (get_domain,
+ get_zone,
+ get_template)
+from marvin.lib.utils import validateList, cleanup_resources
+from marvin.codes import PASS
+from nose.plugins.attrib import attr
+
+class TestPortForwardingRules(cloudstackTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ try:
+ cls._cleanup = []
+ cls.testClient = super(TestPortForwardingRules, cls).getClsTestClient()
+ cls.api_client = cls.testClient.getApiClient()
+ cls.services = cls.testClient.getParsedTestDataConfig()
+ cls.hypervisor = cls.testClient.getHypervisorInfo()
+ # Get Domain, Zone, Template
+ cls.domain = get_domain(cls.api_client)
+ cls.zone = get_zone(
+ cls.api_client,
+ cls.testClient.getZoneForTests())
+ cls.template = get_template(
+ cls.api_client,
+ cls.zone.id,
+ cls.services["ostype"]
+ )
+ if cls.zone.localstorageenabled:
+ cls.storagetype = 'local'
+ cls.services["service_offerings"][
+ "tiny"]["storagetype"] = 'local'
+ else:
+ cls.storagetype = 'shared'
+ cls.services["service_offerings"][
+ "tiny"]["storagetype"] = 'shared'
+
+ cls.services['mode'] = cls.zone.networktype
+ cls.services["virtual_machine"][
+ "hypervisor"] = cls.hypervisor
+ cls.services["virtual_machine"]["zoneid"] = cls.zone.id
+ cls.services["virtual_machine"]["template"] = cls.template.id
+ cls.service_offering = ServiceOffering.create(
+ cls.api_client,
+ cls.services["service_offerings"]["tiny"]
+ )
+ cls._cleanup.append(cls.service_offering)
+ cls.services['mode'] = cls.zone.networktype
+
+ cls.vpc_offering = VpcOffering.create(cls.api_client,
+ cls.services["vpc_offering"]
+ )
+ cls.vpc_offering.update(cls.api_client, state='Enabled')
+ cls._cleanup.append(cls.vpc_offering)
+
+ except Exception as e:
+ cls.tearDownClass()
+ raise Exception("Warning: Exception in setup : %s" % e)
+ return
+
+ def setUp(self):
+
+ self.apiClient = self.testClient.getApiClient()
+ self.cleanup = []
+ self.account = Account.create(
+ self.apiClient,
+ self.services["account"],
+ domainid=self.domain.id
+ )
+ # Getting authentication for user in newly created Account
+ self.user = self.account.user[0]
+ self.userapiclient = self.testClient.getUserApiClient(
+ self.user.username,
+ self.domain.name)
+
+ def tearDown(self):
+ # Clean up, terminate the created volumes
+ cleanup_resources(self.apiClient, self.cleanup)
+ return
+
+ @classmethod
+ def tearDownClass(cls):
+ try:
+ cleanup_resources(cls.api_client, cls._cleanup)
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+
+ def __verify_values(self, expected_vals, actual_vals):
+ """
+ @summary: Function to verify expected and actual values
+ Step1: Initializing return flag to True
+ Step1: Verifying length of expected and actual dictionaries is matching
+ If not matching returning false
+ Step2: Listing all the keys from expected dictionary
+ Step3: Looping through each key from step2 and verifying expected
+ and actual dictionaries have same value
+ If not making return flag to False
+ Step4: returning the return flag after all the values are verified
+ """
+ return_flag = True
+
+ if len(expected_vals) != len(actual_vals):
+ return False
+
+ keys = expected_vals.keys()
+ for i in range(0, len(expected_vals)):
+ exp_val = expected_vals[keys[i]]
+ act_val = actual_vals[keys[i]]
+ if exp_val == act_val:
+ return_flag = return_flag and True
+ else:
+ return_flag = return_flag and False
+ self.debug(
+ "expected Value: %s, is not matching with actual value: %s"
+ %
+ (exp_val, act_val))
+ return return_flag
+
+
+
+ @attr(tags=["advanced"], required_hardware="true")
+ def test_01_create_delete_portforwarding_fornonvpc(self):
+ """
+ @summary: Test to list, create and delete Port Forwarding for
+ IP Address associated to Non VPC network
+ @Steps:
+ Step1: Creating a Network for the user
+ Step2: Associating an IP Addresses for Network
+ Step3: Launching Virtual Machine in network created in step 2
+ Step4: Listing Port Forwarding Rules for the IP Address associated
+ in Step2
+ Step5: Verifying that no Port Forwarding Rules are listed
+ Step6: Creating a Port Forwarding Rule for IP Address associated in
+ Step2
+ Step7: Listing Port Forwarding Rules for the IP Address associated in
+ Step2
+ Step8: Verifying 1 Port Forwarding Rule is listed
+ Step9: Deleting the Port Forwarding Rule created in Step6
+ Step10: Listing Port Forwarding Rules for the IP Address associated in
+ Step2
+ Step11: Verifying that no Port Forwarding Rules are listed
+ """
+ # Listing all the Networks's for a user
+ list_networks_before = Network.list(
+ self.userapiclient,
+ listall=self.services["listall"],
+ type="Isolated"
+ )
+ # Verifying No Networks are listed
+ self.assertIsNone(
+ list_networks_before,
+ "Networks listed for newly created User"
+ )
+ # Listing Network Offerings
+ network_offerings_list = NetworkOffering.list(
+ self.apiClient,
+ forvpc="false",
+ guestiptype="Isolated",
+ state="Enabled",
+ supportedservices="SourceNat,PortForwarding",
+ zoneid=self.zone.id
+ )
+ status = validateList(network_offerings_list)
+ self.assertEquals(
+ PASS,
+ status[0],
+ "Isolated Network Offerings with sourceNat,\
+ PortForwarding enabled are not found"
+ )
+ # Creating a network
+ network = Network.create(
+ self.userapiclient,
+ self.services["network"],
+ accountid=self.account.name,
+ domainid=self.domain.id,
+ networkofferingid=network_offerings_list[0].id,
+ zoneid=self.zone.id
+ )
+ self.assertIsNotNone(
+ network,
+ "Network creation failed"
+ )
+ # Listing all the IP Addresses for a user
+ list_ipaddresses_before = PublicIPAddress.list(
+ self.userapiclient,
+ listall=self.services["listall"]
+ )
+ # Verifying no IP Addresses are listed
+ self.assertIsNone(
+ list_ipaddresses_before,
+ "IP Addresses listed for newly created User"
+ )
+ # Associating an IP Addresses to Network created
+ associated_ipaddress = PublicIPAddress.create(
+ self.userapiclient,
+ services=self.services["network"],
+ networkid=network.id
+ )
+ self.assertIsNotNone(
+ associated_ipaddress,
+ "Failed to Associate IP Address"
+ )
+ # Listing all the IP Addresses for a user
+ list_ipaddresses_after = PublicIPAddress.list(
+ self.userapiclient,
+ listall=self.services["listall"]
+ )
+ status = validateList(list_ipaddresses_after)
+ self.assertEquals(
+ PASS,
+ status[0],
+ "IP Addresses Association Failed"
+ )
+ # Verifying the length of the list is 1
+ self.assertEqual(
+ 1,
+ len(list_ipaddresses_after),
+ "Number of IP Addresses associated are not matching expected"
+ )
+ # Launching a Virtual Machine with above created Network
+ vm_created = VirtualMachine.create(
+ self.userapiclient,
+ self.services["virtual_machine"],
+ accountid=self.account.name,
+ domainid=self.account.domainid,
+ networkids=network.id,
+ serviceofferingid=self.service_offering.id,
+ )
+ self.assertIsNotNone(
+ vm_created,
+ "Failed to launch a VM under network created"
+ )
+ self.cleanup.append(network)
+ # Listing Virtual Machines in running state in above created network
+ list_vms_running = VirtualMachine.list(
+ self.userapiclient,
+ listall=self.services["listall"],
+ state="Running",
+ networkid=network.id
+ )
+ status = validateList(list_vms_running)
+ self.assertEquals(
+ PASS,
+ status[0],
+ "VM Created is not in Running state"
+ )
+ # Verifying the length of the list is 1
+ self.assertEqual(
+ 1,
+ len(list_ipaddresses_after),
+ "VM Created is not in Running state"
+ )
+ self.assertEquals(
+ vm_created.id,
+ list_vms_running[0].id,
+ "VM Created is not in Running state"
+ )
+ # Listing Virtual Machines in stopped state in above created network
+ list_vms_stopped = VirtualMachine.list(
+ self.userapiclient,
+ listall=self.services["listall"],
+ state="Stopped",
+ networkid=network.id
+ )
+ # Verifying no VMs are in stopped state
+ self.assertIsNone(
+ list_vms_stopped,
+ "VM Created is in stopped state"
+ )
+ # Listing Port Forwarding Rules for the IP Address associated
+ list_prtfwdrule_before = NATRule.list(
+ self.userapiclient,
+ listall=self.services["listall"],
+ ipaddressid=associated_ipaddress.ipaddress.id
+ )
+ # Verifying no port forwarding rules are listed
+ self.assertIsNone(
+ list_prtfwdrule_before,
+ "Port Forwarding Rules listed for newly associated IP Address"
+ )
+ # Creating a Port Forwarding rule
+ portfwd_rule = NATRule.create(
+ self.userapiclient,
+ virtual_machine=vm_created,
+ services=self.services["natrule"],
+ ipaddressid=associated_ipaddress.ipaddress.id,
+ )
+ self.assertIsNotNone(
+ portfwd_rule,
+ "Failed to create Port Forwarding Rule"
+ )
+ # Verifying details of Sticky Policy created
+ # Creating expected and actual values dictionaries
+ expected_dict = {
+ "ipaddressid": associated_ipaddress.ipaddress.id,
+ "privateport": str(self.services["natrule"]["privateport"]),
+ "publicport": str(self.services["natrule"]["publicport"]),
+ "protocol": str(self.services["natrule"]["protocol"]).lower(),
+ }
+ actual_dict = {
+ "ipaddressid": portfwd_rule.ipaddressid,
+ "privateport": str(portfwd_rule.privateport),
+ "publicport": str(portfwd_rule.publicport),
+ "protocol": portfwd_rule.protocol,
+ }
+ portfwd_status = self.__verify_values(
+ expected_dict,
+ actual_dict
+ )
+ self.assertEqual(
+ True,
+ portfwd_status,
+ "Created Port Forward Rule details are not as expected"
+ )
+ # Listing Port Forwarding Rules for the IP Address associated
+ list_prtfwdrule_after = NATRule.list(
+ self.userapiclient,
+ listall=self.services["listall"],
+ ipaddressid=associated_ipaddress.ipaddress.id
+ )
+ status = validateList(list_prtfwdrule_after)
+ self.assertEquals(
+ PASS,
+ status[0],
+ "Failed to create Port Forwarding Rule"
+ )
+ # Verifying the length of the list is 1
+ self.assertEqual(
+ 1,
+ len(list_prtfwdrule_after),
+ "Failed to create Port Forwarding Rule"
+ )
+ # Deleting Port Forwarding Rule
+ portfwd_rule.delete(self.userapiclient)
+
+
+ # Creating a Port Forwarding rule with port range
+ portfwd_rule = NATRule.create(
+ self.userapiclient,
+ virtual_machine=vm_created,
+ services=self.services["natrulerange"],
+ ipaddressid=associated_ipaddress.ipaddress.id,
+ )
+ self.assertIsNotNone(
+ portfwd_rule,
+ "Failed to create Port Forwarding Rule"
+ )
+ #update the private port for port forwarding rule
+ updatefwd_rule = portfwd_rule.update(self.userapiclient,
+ portfwd_rule.id,
+ virtual_machine=vm_created,
+ services=self.services["updatenatrulerange"],
+ )
+
+ # Verifying details of Sticky Policy created
+ # Creating expected and actual values dictionaries
+ expected_dict = {
+ "privateport": str(self.services["updatenatrulerange"]["privateport"]),
+ "privateendport": str(self.services["updatenatrulerange"]["privateendport"]),
+ }
+ actual_dict = {
+ "privateport": str(updatefwd_rule.privateport),
+ "privateendport": str(updatefwd_rule.privateendport),
+ }
+ portfwd_status = self.__verify_values(
+ expected_dict,
+ actual_dict
+ )
+ self.assertEqual(
+ True,
+ portfwd_status,
+ "Updated Port Forward Rule details are not as expected"
+ )
+ # Deleting Port Forwarding Rule
+ portfwd_rule.delete(self.userapiclient)
+ # Listing Port Forwarding Rules for the IP Address associated
+ list_prtfwdrule_after = NATRule.list(
+ self.userapiclient,
+ listall=self.services["listall"],
+ ipaddressid=associated_ipaddress.ipaddress.id
+ )
+ # Verifying no port forwarding rules are listed
+ self.assertIsNone(
+ list_prtfwdrule_after,
+ "Port Forwarding Rules listed after deletion"
+ )
+ # Destroying the VM Launched
+ vm_created.delete(self.apiClient)
+ self.cleanup.append(self.account)
+ return
+
diff --git a/test/integration/smoke/test_primary_storage.py b/test/integration/smoke/test_primary_storage.py
index ab67de0a1b3..882df3c22b9 100644
--- a/test/integration/smoke/test_primary_storage.py
+++ b/test/integration/smoke/test_primary_storage.py
@@ -42,6 +42,12 @@ def setUp(self):
self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests())
self.pod = get_pod(self.apiclient, self.zone.id)
self.hypervisor = self.testClient.getHypervisorInfo()
+ self.domain = get_domain(self.apiclient)
+ self.template = get_template(
+ self.apiclient ,
+ self.zone.id ,
+ self.services["ostype"]
+ )
return
@@ -249,6 +255,107 @@ def test_01_primary_storage_iscsi(self):
return
+ @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
+ def test_01_add_primary_storage_disabled_host(self):
+ """Test add primary storage pool with disabled host
+ """
+
+ #Disable a host
+ clusters = list_clusters(
+ self.apiclient,
+ zoneid=self.zone.id
+ )
+ assert isinstance(clusters,list) and len(clusters)>0
+ for cluster in clusters:
+
+ list_hosts_response = list_hosts(
+ self.apiclient,
+ clusterid=cluster.id,
+ type="Routing"
+ )
+ assert isinstance(list_hosts_response,list)
+ if len(list_hosts_response) < 2:
+ continue
+ selected_cluster = cluster
+ selected_host = list_hosts_response[0]
+ Host.update(self.apiclient, id=selected_host.id, allocationstate="Disable")
+
+
+ #create a pool
+ storage_pool_2 = StoragePool.create(
+ self.apiclient,
+ self.services["nfs2"],
+ clusterid=selected_cluster.id,
+ zoneid=self.zone.id,
+ podid=self.pod.id
+ )
+ #self.cleanup.append(storage_pool_2)
+
+ #Enable host and disable others
+ Host.update(self.apiclient, id=selected_host.id, allocationstate="Enable")
+ for host in list_hosts_response :
+ if(host.id == selected_host.id) :
+ continue
+ Host.update(self.apiclient, id=host.id, allocationstate="Disable")
+
+
+ #put other pools in maintenance
+ storage_pool_list = StoragePool.list(self.apiclient, zoneid = self.zone.id)
+ for pool in storage_pool_list :
+ if(pool.id == storage_pool_2.id) :
+ continue
+ StoragePool.update(self.apiclient,id=pool.id, enabled=False)
+
+ #deployvm
+ try:
+ # Create Account
+ account = Account.create(
+ self.apiclient,
+ self.services["account"],
+ domainid=self.domain.id
+ )
+
+ service_offering = ServiceOffering.create(
+ self.apiclient,
+ self.services["service_offerings"]["tiny"]
+ )
+ self.cleanup.append(service_offering)
+
+ self.virtual_machine = VirtualMachine.create(
+ self.apiclient,
+ self.services["virtual_machine"],
+ accountid=account.name,
+ zoneid=self.zone.id,
+ domainid=self.domain.id,
+ templateid=self.template.id,
+ serviceofferingid=service_offering.id
+ )
+ self.cleanup.append(self.virtual_machine)
+ self.cleanup.append(account)
+ finally:
+ #cancel maintenance
+ for pool in storage_pool_list :
+ if(pool.id == storage_pool_2.id) :
+ continue
+ StoragePool.update(self.apiclient,id=pool.id, enabled=True)
+ #Enable all hosts
+ for host in list_hosts_response :
+ if(host.id == selected_host.id) :
+ continue
+ Host.update(self.apiclient, id=host.id, allocationstate="Enable")
+
+ cleanup_resources(self.apiclient, self.cleanup)
+ self.cleanup = []
+ StoragePool.enableMaintenance(self.apiclient,storage_pool_2.id)
+ time.sleep(30);
+ cmd = deleteStoragePool.deleteStoragePoolCmd()
+ cmd.id = storage_pool_2.id
+ cmd.forced = True
+ self.apiclient.deleteStoragePool(cmd)
+
+ return
+
+
class StorageTagsServices:
"""Test Storage Tags Data Class.
"""
@@ -380,7 +487,7 @@ def tearDownClass(cls):
cmd.id = cls.storage_pool_1.id
cmd.forced = True
cls.apiclient.deleteStoragePool(cmd)
-
+
cleanup_resources(cls.apiclient, cls._cleanup)
except Exception as e:
raise Exception("Cleanup failed with %s" % e)
@@ -549,10 +656,10 @@ def test_03_migration_options_storage_tags(self):
listall=True
)
vol = vm_1_volumes[0]
-
+
if self.hypervisor.lower() not in ["vmware", "xenserver"]:
self.virtual_machine_1.stop(self.apiclient)
-
+
# Check migration options for volume
pools_response = StoragePool.listForMigration(
self.apiclient,
diff --git a/test/integration/smoke/test_router_dnsservice.py b/test/integration/smoke/test_router_dnsservice.py
new file mode 100644
index 00000000000..436d9e4382e
--- /dev/null
+++ b/test/integration/smoke/test_router_dnsservice.py
@@ -0,0 +1,275 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import logging
+import dns.resolver
+
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.utils import cleanup_resources
+from marvin.lib.base import (ServiceOffering,
+ VirtualMachine,
+ Account,
+ NATRule,
+ FireWallRule,
+ NetworkOffering,
+ Network)
+from marvin.lib.common import (get_zone,
+ get_template,
+ get_domain,
+ list_routers,
+ list_nat_rules,
+ list_publicIP)
+
+VM1_NAME="drump"
+VM2_NAME="dilton"
+
+class TestRouterDnsService(cloudstackTestCase):
+
+
+ @classmethod
+ def setUpClass(cls):
+ cls.logger = logging.getLogger('TestRouterDnsService')
+ cls.stream_handler = logging.StreamHandler()
+ cls.logger.setLevel(logging.DEBUG)
+ cls.logger.addHandler(cls.stream_handler)
+
+ cls.testClient = super(TestRouterDnsService, cls).getClsTestClient()
+ cls.api_client = cls.testClient.getApiClient()
+ cls.services = cls.testClient.getParsedTestDataConfig()
+
+ cls.domain = get_domain(cls.api_client)
+ cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests())
+ cls.services['mode'] = cls.zone.networktype
+ cls.template = get_template(
+ cls.api_client,
+ cls.zone.id,
+ cls.services["ostype"]
+ )
+ cls.services["virtual_machine"]["zoneid"] = cls.zone.id
+
+ cls.logger.debug("Creating Admin Account for domain %s on zone %s" % (cls.domain.id, cls.zone.id))
+ cls.account = Account.create(
+ cls.api_client,
+ cls.services["account"],
+ admin=True,
+ domainid=cls.domain.id
+ )
+
+ cls.logger.debug("Creating Service Offering on zone %s" % (cls.zone.id))
+ cls.service_offering = ServiceOffering.create(
+ cls.api_client,
+ cls.services["service_offering"]
+ )
+
+ cls.logger.debug("Creating Network Offering on zone %s" % (cls.zone.id))
+ cls.services["isolated_network_offering"]["egress_policy"] = "true"
+ cls.network_offering = NetworkOffering.create(cls.api_client,
+ cls.services["isolated_network_offering"],
+ conservemode=True)
+ cls.network_offering.update(cls.api_client, state='Enabled')
+
+ cls.logger.debug("Creating Network for Account %s using offering %s" % (cls.account.name, cls.network_offering.id))
+ cls.network = Network.create(cls.api_client,
+ cls.services["network"],
+ accountid=cls.account.name,
+ domainid=cls.account.domainid,
+ networkofferingid=cls.network_offering.id,
+ zoneid=cls.zone.id)
+
+ cls.logger.debug("Creating guest VM for Account %s using offering %s" % (cls.account.name, cls.service_offering.id))
+ cls.services["virtual_machine"]["displayname"] = VM1_NAME;
+ cls.services["virtual_machine"]["name"] = VM1_NAME;
+ cls.vm1 = VirtualMachine.create(cls.api_client,
+ cls.services["virtual_machine"],
+ templateid=cls.template.id,
+ accountid=cls.account.name,
+ domainid=cls.domain.id,
+ serviceofferingid=cls.service_offering.id,
+ networkids=[str(cls.network.id)])
+ cls.vm1.password = "password"
+ cls.logger.debug("Created VM named %s" % VM1_NAME);
+
+ cls.services["virtual_machine"]["displayname"] = VM2_NAME;
+ cls.services["virtual_machine"]["name"] = VM2_NAME;
+ cls.vm2 = VirtualMachine.create(cls.api_client,
+ cls.services["virtual_machine"],
+ templateid=cls.template.id,
+ accountid=cls.account.name,
+ domainid=cls.domain.id,
+ serviceofferingid=cls.service_offering.id,
+ networkids=[str(cls.network.id)])
+ cls.vm2.password = "password"
+ cls.logger.debug("Created VM named %s" % VM2_NAME);
+
+ cls.services["natrule1"] = {
+ "privateport": 22,
+ "publicport": 22,
+ "protocol": "TCP"
+ }
+
+ cls.services["configurableData"] = {
+ "host": {
+ "password": "password",
+ "username": "root",
+ "port": 22
+ },
+ "input": "INPUT",
+ "forward": "FORWARD"
+ }
+
+ cls._cleanup = [
+ cls.vm1,
+ cls.vm2,
+ cls.network,
+ cls.network_offering,
+ cls.service_offering,
+ cls.account
+ ]
+
+
+ @classmethod
+ def tearDownClass(cls):
+ try:
+ cleanup_resources(cls.api_client, cls._cleanup)
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+
+
+ def setUp(self):
+ self.apiclient = self.testClient.getApiClient()
+ self.cleanup = []
+
+
+ def tearDown(self):
+ try:
+ cleanup_resources(self.apiclient, self.cleanup)
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+
+
+ def test_router_common(self):
+ """Performs common router tests and returns router public_ips"""
+
+ routers = list_routers(
+ self.apiclient,
+ account=self.account.name,
+ domainid=self.account.domainid
+ )
+
+ self.assertEqual(
+ isinstance(routers, list),
+ True,
+ "Check for list routers response return valid data"
+ )
+
+ self.assertTrue(
+ len(routers) >= 1,
+ "Check list router response"
+ )
+
+ router = routers[0]
+
+ self.assertEqual(
+ router.state,
+ 'Running',
+ "Check list router response for router state"
+ )
+
+ public_ips = list_publicIP(
+ self.apiclient,
+ account=self.account.name,
+ domainid=self.account.domainid,
+ zoneid=self.zone.id
+ )
+
+ self.assertEqual(
+ isinstance(public_ips, list),
+ True,
+ "Check for list public IPs response return valid data"
+ )
+
+ self.assertTrue(
+ len(public_ips) >= 1,
+ "Check public IP list has at least one IP"
+ )
+ return public_ips
+
+
+ @attr(tags=["advanced", "advancedns", "ssh"], required_hardware="true")
+ def test_router_dns_guestipquery(self):
+ """Checks that guest VM can query VR DNS"""
+
+ self.logger.debug("Starting test_router_dns_guestipquery...")
+ public_ip = self.test_router_common()[0]
+
+ self.logger.debug("Creating Firewall rule for VM ID: %s" % self.vm1.id)
+ FireWallRule.create(
+ self.apiclient,
+ ipaddressid=public_ip.id,
+ protocol=self.services["natrule1"]["protocol"],
+ cidrlist=['0.0.0.0/0'],
+ startport=self.services["natrule1"]["publicport"],
+ endport=self.services["natrule1"]["publicport"]
+ )
+
+ self.logger.debug("Creating NAT rule for VM ID: %s" % self.vm1.id)
+ nat_rule1 = NATRule.create(
+ self.apiclient,
+ self.vm1,
+ self.services["natrule1"],
+ public_ip.id
+ )
+ nat_rules = list_nat_rules(
+ self.apiclient,
+ id=nat_rule1.id
+ )
+ self.assertEqual(
+ isinstance(nat_rules, list),
+ True,
+ "Check for list NAT rules response return valid data"
+ )
+ self.assertTrue(
+ len(nat_rules) >= 1,
+ "Check for list NAT rules to have at least one rule"
+ )
+ self.assertEqual(
+ nat_rules[0].state,
+ 'Active',
+ "Check list port forwarding rules"
+ )
+
+ result1 = None
+ try:
+ self.logger.debug("SSH into guest VM with IP: %s" % nat_rule1.ipaddress)
+ ssh = self.vm1.get_ssh_client(ipaddress=nat_rule1.ipaddress, port=self.services['natrule1']["publicport"], retries=8)
+ result1 = str(ssh.execute("nslookup %s" % VM1_NAME))
+ self.logger.debug("nslookup %s: %s " % (VM1_NAME, result1))
+ result2 = str(ssh.execute("nslookup %s" % VM2_NAME))
+ self.logger.debug("nslookup %s: %s " % (VM2_NAME, result2))
+ except Exception as e:
+ self.fail("Failed to SSH into VM - %s due to exception: %s" % (nat_rule1.ipaddress, e))
+
+ if not result1:
+ self.fail("Did not to receive any response from the guest VM, failing.")
+
+ self.assertTrue(VM1_NAME in result1 and "#53" in result1,
+ "VR DNS should serve requests from guest network, ping for %s successful." % VM1_NAME)
+ self.assertTrue(VM2_NAME in result2 and "#53" in result2,
+ "VR DNS should serve requests from guest network, ping for %s successful." % VM2_NAME)
+
+ return
diff --git a/test/integration/smoke/test_staticroles.py b/test/integration/smoke/test_staticroles.py
index 5421f6b4e3c..2300da5cd6e 100644
--- a/test/integration/smoke/test_staticroles.py
+++ b/test/integration/smoke/test_staticroles.py
@@ -68,7 +68,7 @@ def setUp(self):
except Exception:
self.debug("Failed to ssh into mgmt server host and grab commands.properties file")
testDir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
- localFileName = os.path.abspath(testDir + "/../../../client/tomcatconf/commands.properties.in")
+ localFileName = os.path.abspath(testDir + "/../../../client/conf/commands.properties.in")
if os.path.isfile(localFileName):
self.info("Detected that we're running in developer mode with maven, using file at:" + localFileName)
with open(localFileName) as f:
diff --git a/test/integration/smoke/test_templates.py b/test/integration/smoke/test_templates.py
index a621a0a6c12..8d76de36a59 100644
--- a/test/integration/smoke/test_templates.py
+++ b/test/integration/smoke/test_templates.py
@@ -17,6 +17,8 @@
""" BVT tests for Templates ISO
"""
#Import Local Modules
+from marvin.cloudstackException import *
+from marvin.cloudstackAPI import *
from marvin.codes import FAILED
from marvin.cloudstackTestCase import cloudstackTestCase, unittest
from marvin.cloudstackAPI import listZones
@@ -82,6 +84,203 @@ def create(apiclient, services, volumeid=None, account=None, domainid=None, proj
cmd.projectid = projectid
return apiclient.createTemplate(cmd)
+class TestCreateTemplateWithChecksum(cloudstackTestCase):
+ def setUp(self):
+ self.testClient = super(TestCreateTemplateWithChecksum, self).getClsTestClient()
+ self.apiclient = self.testClient.getApiClient()
+ self.dbclient = self.testClient.getDbConnection()
+ self.cleanup = []
+
+ self.services = self.testClient.getParsedTestDataConfig()
+ self.unsupportedHypervisor = False
+ self.hypervisor = self.testClient.getHypervisorInfo()
+ if self.hypervisor.lower() in ['lxc']:
+ # Template creation from root volume is not supported in LXC
+ self.unsupportedHypervisor = True
+ return
+
+ # Get Zone, Domain and templates
+ self.domain = get_domain(self.apiclient)
+ self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests())
+
+ if "kvm" in self.hypervisor.lower():
+ self.test_template = registerTemplate.registerTemplateCmd()
+ self.test_template = registerTemplate.registerTemplateCmd()
+ self.test_template.checksum = "{SHA-1}" + "bf580a13f791d86acf3449a7b457a91a14389264"
+ self.test_template.hypervisor = self.hypervisor
+ self.test_template.zoneid = self.zone.id
+ self.test_template.name = 'test sha-2333'
+ self.test_template.displaytext = 'test sha-1'
+ self.test_template.url = "http://dl.openvm.eu/cloudstack/macchinina/x86_64/macchinina-kvm.qcow2.bz2"
+ self.test_template.format = "QCOW2"
+ self.test_template.ostypeid = self.getOsType("Other Linux (64-bit)")
+ self.md5 = "ada77653dcf1e59495a9e1ac670ad95f"
+ self.sha256 = "0efc03633f2b8f5db08acbcc5dc1be9028572dfd8f1c6c8ea663f0ef94b458c5"
+
+ if "vmware" in self.hypervisor.lower():
+ self.test_template = registerTemplate.registerTemplateCmd()
+ self.test_template = registerTemplate.registerTemplateCmd()
+ self.test_template.checksum = "{SHA-1}" + "b25d404de8335b4348ff01e49a95b403c90df466"
+ self.test_template.hypervisor = self.hypervisor
+ self.test_template.zoneid = self.zone.id
+ self.test_template.name = 'test sha-2333'
+ self.test_template.displaytext = 'test sha-1'
+ self.test_template.url = "http://dl.openvm.eu/cloudstack/macchinina/x86_64/macchinina-vmware.ova"
+ self.test_template.format = "OVA"
+ self.test_template.ostypeid = self.getOsType("Other Linux (64-bit)")
+ self.md5 = "d6d97389b129c7d898710195510bf4fb"
+ self.sha256 = "f57b59f118ab59284a70d6c63229d1de8f2d69bffc5a82b773d6c47e769c12d9"
+
+ if "xen" in self.hypervisor.lower():
+ self.test_template = registerTemplate.registerTemplateCmd()
+ self.test_template = registerTemplate.registerTemplateCmd()
+ self.test_template.checksum = "{SHA-1}" + "427fad501d0d8a1d63b8600a9a469fbf91191314"
+ self.test_template.hypervisor = self.hypervisor
+ self.test_template.zoneid = self.zone.id
+ self.test_template.name = 'test sha-2333'
+ self.test_template.displaytext = 'test sha-1'
+ self.test_template.url = "http://dl.openvm.eu/cloudstack/macchinina/x86_64/macchinina-xen.vhd.bz2"
+ self.test_template.format = "VHD"
+ self.test_template.ostypeid = self.getOsType("Other Linux (64-bit)")
+ self.md5 = "54ebc933e6e07ae58c0dc97dfd37c824"
+ self.sha256 = "bddd9876021d33df9792b71ae4b776598680ac68ecf55e9d9af33c80904cc1f3"
+
+ if self.unsupportedHypervisor:
+ self.skipTest("Skipping test because unsupported hypervisor\
+ %s" % self.hypervisor)
+ return
+
+ def tearDown(self):
+ try:
+ # Clean up the created templates
+ for temp in self.cleanup:
+ cmd = deleteTemplate.deleteTemplateCmd()
+ cmd.id = temp.id
+ cmd.zoneid = self.zone.id
+ self.apiclient.deleteTemplate(cmd)
+
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+ return
+
+ @attr(tags=["advanced", "smoke"], required_hardware="true")
+ def test_02_create_template_with_checksum_sha1(self):
+ template = self.registerTemplate(self.test_template)
+ self.download(self.apiclient, template.id)
+
+ @attr(tags=["advanced", "smoke"], required_hardware="true")
+ def test_03_create_template_with_checksum_sha256(self):
+ self.test_template.checksum = "{SHA-256}" + self.sha256
+ template = self.registerTemplate(self.test_template)
+ self.download(self.apiclient, template.id)
+
+ @attr(tags=["advanced", "smoke"], required_hardware="true")
+ def test_04_create_template_with_checksum_md5(self):
+ self.test_template.checksum = "{md5}" + self.md5
+ template = self.registerTemplate(self.test_template)
+ self.download(self.apiclient, template.id)
+
+ @attr(tags=["advanced", "smoke"], required_hardware="true")
+ def test_02_1_create_template_with_checksum_sha1_negative(self):
+ self.test_template.checksum = "{sha-1}" + "someInvalidValue"
+ template = self.registerTemplate(self.test_template)
+
+ try:
+ self.download(self.apiclient, template.id)
+ except Exception as e:
+ print "Negative Test Passed - Exception Occurred Under template download " \
+ "%s" % GetDetailExceptionInfo(e)
+ else:
+ self.fail("Negative Test Failed - Exception DID NOT Occurred Under template download ")
+
+ @attr(tags=["advanced", "smoke"], required_hardware="true")
+ def test_03_1_create_template_with_checksum_sha256_negative(self):
+ self.test_template.checksum = "{SHA-256}" + "someInvalidValue"
+ template = self.registerTemplate(self.test_template)
+
+ try:
+ self.download(self.apiclient, template.id)
+ except Exception as e:
+ print "Negative Test Passed - Exception Occurred Under template download " \
+ "%s" % GetDetailExceptionInfo(e)
+ else:
+ self.fail("Negative Test Failed - Exception DID NOT Occurred Under template download ")
+
+ @attr(tags=["advanced", "smoke"], required_hardware="true")
+ def test_04_1_create_template_with_checksum_md5_negative(self):
+ self.test_template.checksum = "{md5}" + "someInvalidValue"
+ template = self.registerTemplate(self.test_template)
+
+ try:
+ self.download(self.apiclient, template.id)
+ except Exception as e:
+ print "Negative Test Passed - Exception Occurred Under template download " \
+ "%s" % GetDetailExceptionInfo(e)
+ else:
+ self.fail("Negative Test Failed - Exception DID NOT Occurred Under template download ")
+
+ @attr(tags=["advanced", "smoke"], required_hardware="true")
+ def test_05_create_template_with_no_checksum(self):
+ self.test_template.checksum = None
+ template = self.registerTemplate(self.test_template)
+ self.download(self.apiclient, template.id)
+
+ def registerTemplate(self, cmd):
+ temp = self.apiclient.registerTemplate(cmd)[0]
+ self.cleanup.append(temp)
+ return temp
+
+ def getOsType(self, param):
+ cmd = listOsTypes.listOsTypesCmd()
+ cmd.description = param
+ return self.apiclient.listOsTypes(cmd)[0].id
+
+ def download(self, apiclient, template_id, retries=12, interval=5):
+ """Check if template download will finish in 1 minute"""
+ while retries > -1:
+ time.sleep(interval)
+ template_response = Template.list(
+ apiclient,
+ id=template_id,
+ zoneid=self.zone.id,
+ templatefilter='self'
+ )
+
+ if isinstance(template_response, list):
+ template = template_response[0]
+ if not hasattr(template, 'status') or not template or not template.status:
+ retries = retries - 1
+ continue
+
+ # If template is ready,
+ # template.status = Download Complete
+ # Downloading - x% Downloaded
+ # if Failed
+ # Error - Any other string
+ if 'Failed' in template.status:
+ raise Exception(
+ "Failed to download template: status - %s" %
+ template.status)
+
+ elif template.status == 'Download Complete' and template.isready:
+ return
+
+ elif 'Downloaded' in template.status:
+ retries = retries - 1
+ continue
+
+ elif 'Installing' not in template.status:
+ if retries >= 0:
+ retries = retries - 1
+ continue
+ raise Exception(
+ "Error in downloading template: status - %s" %
+ template.status)
+
+ else:
+ retries = retries - 1
+ raise Exception("Template download failed exception.")
+
class TestCreateTemplate(cloudstackTestCase):
diff --git a/test/integration/smoke/test_volumes.py b/test/integration/smoke/test_volumes.py
index 28087b11262..fca65f2841c 100644
--- a/test/integration/smoke/test_volumes.py
+++ b/test/integration/smoke/test_volumes.py
@@ -245,7 +245,7 @@ def test_01_create_volume(self):
elif list_volume_response[0].hypervisor.lower() == "hyperv":
ret = checkVolumeSize(ssh_handle=ssh,volume_name="/dev/sdb",size_to_verify=vol_sz)
else:
- ret = checkVolumeSize(ssh_handle=ssh,size_to_verify=vol_sz)
+ ret = checkVolumeSize(ssh_handle=ssh,volume_name="/dev/sdb",size_to_verify=vol_sz)
self.debug(" Volume Size Expected %s Actual :%s" %(vol_sz,ret[1]))
self.virtual_machine.detach_volume(self.apiClient, volume)
self.assertEqual(ret[0],SUCCESS,"Check if promised disk size actually available")
diff --git a/test/integration/testpaths/testpath_delta_snapshots.py b/test/integration/testpaths/testpath_delta_snapshots.py
new file mode 100644
index 00000000000..cb8461b4394
--- /dev/null
+++ b/test/integration/testpaths/testpath_delta_snapshots.py
@@ -0,0 +1,540 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+""" Test cases for Delta Snapshots Test Path
+"""
+
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.utils import (cleanup_resources,
+ validateList,
+ is_snapshot_on_nfs)
+from marvin.lib.base import (Account,
+ ServiceOffering,
+ Template,
+ VirtualMachine,
+ Volume,
+ Configurations,
+ Snapshot
+ )
+from marvin.lib.common import (get_domain,
+ get_zone,
+ get_template,
+ list_volumes,
+ createChecksum,
+ compareChecksum
+ )
+from marvin.sshClient import SshClient
+from marvin.codes import (PASS, FAIL, BACKED_UP, ROOT, DATA)
+import time
+
+
+def checkIntegrityOfSnapshot(
+ self, snapshotsToRestore, checksumToCompare, disk_type=ROOT):
+ """
+ Check integrity of snapshot created of ROOT or DATA Disk:
+
+ If ROOT Disk: Deploy a Vm from a template created from the snapshot
+ and checking the contents of the ROOT disk.
+ If DATA Disk: Users can create a volume from the snapshot.
+ The volume can then be mounted to a VM and files
+ recovered as needed.
+
+ Inputs:
+ 1. snapshotsToRestore: Snapshots whose integrity is
+ to be checked.
+
+ 2. checksumToCompare: The contents of ROOT Disk to be compared.
+
+ 3. disk_type: The type of disk - ROOT or DATA Disk
+ of which snapshot was created.
+
+ """
+ if disk_type == ROOT:
+ # Create template from snapshot
+ template_from_snapshot = Template.create_from_snapshot(
+ self.apiclient,
+ snapshotsToRestore,
+ self.testdata["template_2"])
+
+ self.assertNotEqual(
+ template_from_snapshot,
+ None,
+ "Check if result exists in list item call"
+ )
+
+ # Deploy VM
+ vm_from_temp = VirtualMachine.create(
+ self.apiclient,
+ self.testdata["small"],
+ templateid=template_from_snapshot.id,
+ accountid=self.account.name,
+ domainid=self.account.domainid,
+ serviceofferingid=self.service_offering.id,
+ zoneid=self.zone.id,
+ mode=self.zone.networktype
+ )
+
+ self.assertNotEqual(
+ vm_from_temp,
+ None,
+ "Check if result exists in list item call"
+ )
+
+ # Verify contents of ROOT disk match with snapshot
+
+ compareChecksum(
+ self.apiclient,
+ service=self.testdata,
+ original_checksum=checksumToCompare,
+ disk_type="rootdiskdevice",
+ virt_machine=vm_from_temp
+ )
+
+ vm_from_temp.delete(self.apiclient)
+ template_from_snapshot.delete(self.apiclient)
+ else:
+ volumeFormSnap = Volume.create_from_snapshot(
+ self.apiclient,
+ snapshotsToRestore.id,
+ self.testdata["volume"],
+ account=self.account.name,
+ domainid=self.account.domainid,
+ zoneid=self.zone.id
+ )
+
+ temp_vm = VirtualMachine.create(
+ self.apiclient,
+ self.testdata["small"],
+ templateid=self.template.id,
+ accountid=self.account.name,
+ domainid=self.account.domainid,
+ serviceofferingid=self.service_offering.id,
+ zoneid=self.zone.id,
+ mode=self.zone.networktype
+ )
+ temp_vm.attach_volume(
+ self.apiclient,
+ volumeFormSnap
+ )
+
+ temp_vm.reboot(self.apiclient)
+
+ compareChecksum(
+ self.apiclient,
+ self.testdata,
+ checksumToCompare,
+ "datadiskdevice_1",
+ temp_vm
+ )
+
+ temp_vm.delete(self.apiclient)
+ volumeFormSnap.delete(self.apiclient)
+
+ return
+
+
+class TestDeltaSnapshots(cloudstackTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ testClient = super(TestDeltaSnapshots, cls).getClsTestClient()
+ cls.apiclient = testClient.getApiClient()
+ cls.testdata = testClient.getParsedTestDataConfig()
+ cls.hypervisor = cls.testClient.getHypervisorInfo()
+
+ # Get Zone, Domain and templates
+ cls.domain = get_domain(cls.apiclient)
+ cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+
+ cls.template = get_template(
+ cls.apiclient,
+ cls.zone.id,
+ cls.testdata["ostype"])
+
+ cls.snapshots_created = []
+ cls._cleanup = []
+
+ cls.mgtSvrDetails = cls.config.__dict__["mgtSvr"][0].__dict__
+ cls.skiptest = False
+
+ if cls.hypervisor.lower() not in ["xenserver"]:
+ cls.skiptest = True
+
+ try:
+
+ # Create an account
+ cls.account = Account.create(
+ cls.apiclient,
+ cls.testdata["account"],
+ domainid=cls.domain.id
+ )
+ cls._cleanup.append(cls.account)
+
+ # Create user api client of the account
+ cls.userapiclient = testClient.getUserApiClient(
+ UserName=cls.account.name,
+ DomainName=cls.account.domain
+ )
+
+ # Create Service offering
+ cls.service_offering = ServiceOffering.create(
+ cls.apiclient,
+ cls.testdata["service_offering"],
+ )
+ cls._cleanup.append(cls.service_offering)
+
+ if cls.testdata["configurableData"][
+ "restartManagementServerThroughTestCase"]:
+ # Set snapshot delta max value
+ Configurations.update(cls.apiclient,
+ name="snapshot.delta.max",
+ value="3"
+ )
+
+ # Restart management server
+ cls.RestartServer()
+ time.sleep(120)
+
+ configs = Configurations.list(
+ cls.apiclient,
+ name="snapshot.delta.max")
+ cls.delta_max = configs[0].value
+
+ cls.vm = VirtualMachine.create(
+ cls.apiclient,
+ cls.testdata["small"],
+ templateid=cls.template.id,
+ accountid=cls.account.name,
+ domainid=cls.account.domainid,
+ serviceofferingid=cls.service_offering.id,
+ zoneid=cls.zone.id,
+ mode=cls.zone.networktype
+ )
+
+ except Exception as e:
+ cls.tearDownClass()
+ raise e
+ return
+
+ @classmethod
+ def tearDownClass(cls):
+ try:
+ cleanup_resources(cls.apiclient, cls._cleanup)
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+
+ def setUp(self):
+ if self.skiptest:
+ self.skipTest(
+ "Delta snapshot not supported on %s" %
+ self.hypervisor)
+ self.apiclient = self.testClient.getApiClient()
+ self.dbclient = self.testClient.getDbConnection()
+ self.cleanup = []
+
+ def tearDown(self):
+ try:
+ for snapshot in self.snapshots_created:
+ snapshot.delete(self.apiclient)
+ cleanup_resources(self.apiclient, self.cleanup)
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+ return
+
+ @classmethod
+ def RestartServer(cls):
+ """Restart management server"""
+
+ sshClient = SshClient(
+ cls.mgtSvrDetails["mgtSvrIp"],
+ 22,
+ cls.mgtSvrDetails["user"],
+ cls.mgtSvrDetails["passwd"]
+ )
+ command = "service cloudstack-management restart"
+ sshClient.execute(command)
+
+ return
+
+ @attr(tags=["advanced", "basic"], required_hardware="true")
+ def test_01_delta_snapshots(self):
+ """ Delta Snapshots
+ 1. Create file on ROOT disk of deployed VM.
+ 2. Create Snapshot of ROOT disk.
+ 3. Verify secondary storage count.
+ 4. Check integrity of Full Snapshot.
+ 5. Delete delta snaphshot and check integrity of\
+ remaining snapshots.
+ 6. Delete full snapshot and verify it is deleted from\
+ secondary storage.
+ """
+ checksum_created = []
+ full_snapshot_count = 0
+ delta_snapshot_count = 0
+
+ # Mulitply delta max value by 2 to set loop counter
+ # to create 2 Snapshot chains
+ snapshot_loop_count = int(self.delta_max) * 2
+
+ # Get ROOT Volume
+ root_volumes_list = list_volumes(
+ self.apiclient,
+ virtualmachineid=self.vm.id,
+ type=ROOT,
+ listall=True
+ )
+
+ status = validateList(root_volumes_list)
+ self.assertEqual(
+ status[0],
+ PASS,
+ "Check listVolumes response for ROOT Disk")
+
+ root_volume = root_volumes_list[0]
+
+ # Get Secondary Storage Value from Database
+ qryresult_before_snapshot = self.dbclient.execute(
+ " select id, account_name, secondaryStorageTotal\
+ from account_view where account_name = '%s';" %
+ self.account.name)
+
+ self.assertNotEqual(
+ len(qryresult_before_snapshot),
+ 0,
+ "Check sql query to return SecondaryStorageTotal of account")
+
+ storage_qry_result_old = qryresult_before_snapshot[0]
+ secondary_storage_old = storage_qry_result_old[2]
+
+ # Create Snapshots
+
+ for i in range(snapshot_loop_count):
+
+ # Step 1
+ checksum_root = createChecksum(
+ self.testdata,
+ self.vm,
+ root_volume,
+ "rootdiskdevice")
+
+ time.sleep(30)
+ checksum_created.append(checksum_root)
+
+ # Step 2
+ root_vol_snapshot = Snapshot.create(
+ self.apiclient,
+ root_volume.id)
+
+ self.snapshots_created.append(root_vol_snapshot)
+
+ snapshots_list = Snapshot.list(self.apiclient,
+ id=root_vol_snapshot.id)
+
+ status = validateList(snapshots_list)
+ self.assertEqual(status[0], PASS, "Check listSnapshots response")
+
+ # Verify Snapshot state
+ self.assertEqual(
+ snapshots_list[0].state.lower() in [
+ BACKED_UP,
+ ],
+ True,
+ "Snapshot state is not as expected. It is %s" %
+ snapshots_list[0].state
+ )
+
+ self.assertEqual(
+ snapshots_list[0].volumeid,
+ root_volume.id,
+ "Snapshot volume id is not matching with the vm's volume id")
+
+ # Step 3
+ qryresult_after_snapshot = self.dbclient.execute(
+ " select id, account_name, secondaryStorageTotal\
+ from account_view where account_name = '%s';" %
+ self.account.name)
+
+ self.assertNotEqual(
+ len(qryresult_after_snapshot),
+ 0,
+ "Check sql query to return SecondaryStorageTotal of account")
+
+ storage_qry_result_from_database = qryresult_after_snapshot[0]
+ secondary_storage_from_database = storage_qry_result_from_database[
+ 2]
+
+ snapshot_size = snapshots_list[0].physicalsize
+ secondary_storage_after_snapshot = secondary_storage_old + \
+ snapshot_size
+
+ # Reset full_snapshot_count to 0 before start of new snapshot chain
+ if delta_snapshot_count == (int(self.delta_max) - 1):
+ full_snapshot_count = 0
+ delta_snapshot_count = 0
+
+ # Full Snapshot of each Snapshot chain
+ if full_snapshot_count == 0:
+
+ full_snapshot_count += 1
+ full_snapshot_size = snapshot_size
+
+ # Check secondary storage count for Full Snapshots
+ self.assertEqual(
+ secondary_storage_from_database,
+ secondary_storage_after_snapshot,
+ "Secondary storage count after full snapshot\
+ should be incremented by size of snapshot.")
+ # Step 4
+ checkIntegrityOfSnapshot(
+ self,
+ snapshots_list[0],
+ checksum_root,
+ disk_type=DATA)
+
+ else:
+
+ # Delta Snapshot of each Snapshot chain
+ delta_snapshot_count += 1
+ delta_snapshot_size = snapshot_size
+
+ # Check secondary storage count for Delta Snapshots
+ self.assertTrue(delta_snapshot_size < full_snapshot_size,
+ "Delta Snapshot size should be less than\
+ Full Snapshot.")
+
+ self.assertEqual(
+ secondary_storage_from_database,
+ secondary_storage_after_snapshot,
+ "Secondary storage count after delta snapshot\
+ should be incremented by size of snapshot.")
+
+ secondary_storage_old = secondary_storage_from_database
+
+ # Step 5
+
+ # Check in Secondary Storage- Snapshots: S1, S2, S3 are present
+ for i in range(int(self.delta_max)):
+ self.assertTrue(
+ is_snapshot_on_nfs(
+ self.apiclient,
+ self.dbclient,
+ self.config,
+ self.zone.id,
+ self.snapshots_created[i].id),
+ "Check: Snapshot is not on Secondary Storage.")
+
+ # Delete S2
+
+ Snapshot.delete(self.snapshots_created[1], self.apiclient)
+
+ snapshots_list = Snapshot.list(self.apiclient,
+ id=self.snapshots_created[1].id)
+
+ status = validateList(snapshots_list)
+ self.assertEqual(status[0], FAIL, "Snapshots Not Deleted.")
+
+ # Check integrity of Snapshots for S1 and S3
+ checkIntegrityOfSnapshot(
+ self,
+ self.snapshots_created[0],
+ checksum_created[0],
+ disk_type=DATA)
+
+ checkIntegrityOfSnapshot(
+ self,
+ self.snapshots_created[2],
+ checksum_created[2],
+ disk_type=DATA)
+
+ # Delete S3
+
+ Snapshot.delete(self.snapshots_created[2], self.apiclient)
+
+ snapshots_list = Snapshot.list(self.apiclient,
+ id=self.snapshots_created[2].id)
+
+ status = validateList(snapshots_list)
+ self.assertEqual(status[0], FAIL, "Snapshots Not Deleted.")
+
+ # Check in Secondary Storage - Snapshots: S2, S3 are deleted
+ self.assertFalse(
+ is_snapshot_on_nfs(
+ self.apiclient,
+ self.dbclient,
+ self.config,
+ self.zone.id,
+ self.snapshots_created[2].id),
+ "Check: Snapshot 2 is still on Secondary Storage. Not Deleted.")
+
+ self.assertFalse(
+ is_snapshot_on_nfs(
+ self.apiclient,
+ self.dbclient,
+ self.config,
+ self.zone.id,
+ self.snapshots_created[1].id),
+ "Check: Snapshot 3 is still on Secondary Storage. Not Deleted.")
+
+ # Restore Snapshots for S1
+ checkIntegrityOfSnapshot(
+ self,
+ self.snapshots_created[0],
+ checksum_created[0],
+ disk_type=DATA)
+
+ # Step 6
+ # Delete S1
+
+ Snapshot.delete(self.snapshots_created[0], self.apiclient)
+
+ snapshots_list = Snapshot.list(self.apiclient,
+ id=self.snapshots_created[0].id)
+
+ status = validateList(snapshots_list)
+ self.assertEqual(status[0], FAIL, "Snapshots Not Deleted.")
+
+ # Check in Secondary Storage - Snapshots: All - S1, S2, S3 are deleted
+
+ self.assertFalse(
+ is_snapshot_on_nfs(
+ self.apiclient,
+ self.dbclient,
+ self.config,
+ self.zone.id,
+ self.snapshots_created[2].id),
+ "Check: Snapshot 3 is still on Secondary Storage. Not Deleted.")
+
+ self.assertFalse(
+ is_snapshot_on_nfs(
+ self.apiclient,
+ self.dbclient,
+ self.config,
+ self.zone.id,
+ self.snapshots_created[1].id),
+ "Check: Snapshot 2 is still on Secondary Storage. Not Deleted.")
+
+ self.assertFalse(
+ is_snapshot_on_nfs(
+ self.apiclient,
+ self.dbclient,
+ self.config,
+ self.zone.id,
+ self.snapshots_created[0].id),
+ "Check: Snapshot 1 is still on Secondary Storage. Not Deleted.")
+
+ return
+
diff --git a/test/pom.xml b/test/pom.xml
index c052eec1f11..1812b0390cf 100644
--- a/test/pom.xml
+++ b/test/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
diff --git a/test/src/com/cloud/test/ui/AddAndDeleteATemplate.java b/test/src/com/cloud/test/ui/AddAndDeleteATemplate.java
index b0b7183774f..b46f9228217 100644
--- a/test/src/com/cloud/test/ui/AddAndDeleteATemplate.java
+++ b/test/src/com/cloud/test/ui/AddAndDeleteATemplate.java
@@ -57,7 +57,7 @@ public void testAddAndDeleteTemplate() throws Exception {
}
} catch (Exception ex) {
s_logger.info("[ignored]"
- + "error during clicking test on template: " + e.getLocalizedMessage());
+ + "error during clicking test on template: " + ex.getLocalizedMessage());
}
for (int second = 0;; second++) {
diff --git a/tools/apidoc/build-apidoc.sh b/tools/apidoc/build-apidoc.sh
index 8ab69c83739..4e1f9a639d1 100755
--- a/tools/apidoc/build-apidoc.sh
+++ b/tools/apidoc/build-apidoc.sh
@@ -47,7 +47,7 @@ fi
CP=$PATHSEP/
-java -cp $CP$PATHSEP$TARGETJARDIR/*$PATHSEP$DEPSDIR/* com.cloud.api.doc.ApiXmlDocWriter -d "$DISTDIR" $*
+java -cp $CP$PATHSEP$TARGETJARDIR$PATHSEP$DEPSDIR com.cloud.api.doc.ApiXmlDocWriter -d "$DISTDIR" $*
if [ $? -ne 0 ]
then
diff --git a/tools/apidoc/gen_toc.py b/tools/apidoc/gen_toc.py
index 0fd97754176..cffc5d4e4db 100644
--- a/tools/apidoc/gen_toc.py
+++ b/tools/apidoc/gen_toc.py
@@ -171,6 +171,22 @@
'StratosphereSsp' : ' Stratosphere SSP',
'Metrics' : 'Metrics',
'Infrastructure' : 'Metrics',
+ 'listNetscalerControlCenter' : 'Load Balancer',
+ 'listRegisteredServicePackages': 'Load Balancer',
+ 'listNsVpx' : 'Load Balancer',
+ 'destroyNsVPx': 'Load Balancer',
+ 'deployNetscalerVpx' : 'Load Balancer',
+ 'deleteNetscalerControlCenter' : 'Load Balancer',
+ 'stopNetScalerVpx' : 'Load Balancer',
+ 'deleteServicePackageOffering' : 'Load Balancer',
+ 'destroyNsVpx' : 'Load Balancer',
+ 'startNsVpx' : 'Load Balancer',
+ 'listAnnotations' : 'Annotations',
+ 'addAnnotation' : 'Annotations',
+ 'removeAnnotation' : 'Annotations',
+ 'CA': 'Certificate',
+ 'listElastistorInterface': 'Misc',
+ 'cloudian': 'Cloudian'
}
diff --git a/tools/apidoc/pom.xml b/tools/apidoc/pom.xml
index c750c44f06c..61c1ccd5937 100644
--- a/tools/apidoc/pom.xml
+++ b/tools/apidoc/pom.xml
@@ -17,12 +17,12 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-tools</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<properties>
- <client.config.base>../../client/target/cloud-client-ui-${project.version}/WEB-INF/</client.config.base>
- <client.config.jars>${client.config.base}/lib</client.config.jars>
+ <client.config.base>../../client/target/</client.config.base>
+ <client.config.jars>${client.config.base}/cloud-client-ui-${project.version}.jar</client.config.jars>
<client.config.conf>${client.config.base}/classes</client.config.conf>
</properties>
diff --git a/tools/checkstyle/pom.xml b/tools/checkstyle/pom.xml
index 17c291e1572..c8555a3c748 100644
--- a/tools/checkstyle/pom.xml
+++ b/tools/checkstyle/pom.xml
@@ -24,7 +24,7 @@
<name>Apache CloudStack Developer Tools - Checkstyle Configuration</name>
<groupId>org.apache.cloudstack</groupId>
<artifactId>checkstyle</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<build>
<plugins>
diff --git a/tools/cli/README b/tools/cli/README
index f8bfebea4ed..0508d0be87d 100644
--- a/tools/cli/README
+++ b/tools/cli/README
@@ -1 +1 @@
-Moved to https://git-wip-us.apache.org/repos/asf?p=cloudstack-cloudmonkey.git
+Moved to https://gitbox.apache.org/repos/asf?p=cloudstack-cloudmonkey.git
diff --git a/tools/devcloud-kvm/pom.xml b/tools/devcloud-kvm/pom.xml
index 4c798e2d0d2..155e0b7231a 100644
--- a/tools/devcloud-kvm/pom.xml
+++ b/tools/devcloud-kvm/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-tools</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/tools/devcloud4/pom.xml b/tools/devcloud4/pom.xml
index b87dbef038c..c3124e00bb7 100644
--- a/tools/devcloud4/pom.xml
+++ b/tools/devcloud4/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-tools</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile
index c9c250f7be3..a927e9b3c3d 100644
--- a/tools/docker/Dockerfile
+++ b/tools/docker/Dockerfile
@@ -20,7 +20,7 @@
FROM ubuntu:16.04
MAINTAINER "Apache CloudStack" <de...@cloudstack.apache.org>
-LABEL Vendor="Apache.org" License="ApacheV2" Version="4.10.1.0-SNAPSHOT"
+LABEL Vendor="Apache.org" License="ApacheV2" Version="4.11.0.0-SNAPSHOT"
RUN apt-get -y update && apt-get install -y \
genisoimage \
diff --git a/tools/docker/Dockerfile.centos6 b/tools/docker/Dockerfile.centos6
index c7393058202..7ccd81467ba 100644
--- a/tools/docker/Dockerfile.centos6
+++ b/tools/docker/Dockerfile.centos6
@@ -18,7 +18,7 @@
FROM centos:6
MAINTAINER "Apache CloudStack" <de...@cloudstack.apache.org>
-LABEL Vendor="Apache.org" License="ApacheV2" Version="4.10.1.0-SNAPSHOT"
+LABEL Vendor="Apache.org" License="ApacheV2" Version="4.11.0.0-SNAPSHOT"
ENV PKG_URL=https://builds.cloudstack.org/job/package-master-rhel63/lastSuccessfulBuild/artifact/dist/rpmbuild/RPMS/x86_64
@@ -26,8 +26,8 @@ ENV PKG_URL=https://builds.cloudstack.org/job/package-master-rhel63/lastSuccessf
RUN rpm -i http://dev.mysql.com/get/Downloads/Connector-Python/mysql-connector-python-2.1.3-1.el6.x86_64.rpm
RUN yum install -y nc wget \
- ${PKG_URL}/cloudstack-common-4.10.1.0-SNAPSHOT.el6.x86_64.rpm \
- ${PKG_URL}/cloudstack-management-4.10.1.0-SNAPSHOT.el6.x86_64.rpm
+ ${PKG_URL}/cloudstack-common-4.11.0.0-SNAPSHOT.el6.x86_64.rpm \
+ ${PKG_URL}/cloudstack-management-4.11.0.0-SNAPSHOT.el6.x86_64.rpm
RUN cd /etc/cloudstack/management; \
ln -s tomcat6-nonssl.conf tomcat6.conf; \
diff --git a/tools/docker/Dockerfile.marvin b/tools/docker/Dockerfile.marvin
index e6e440ca352..e6811bfecb9 100644
--- a/tools/docker/Dockerfile.marvin
+++ b/tools/docker/Dockerfile.marvin
@@ -20,11 +20,11 @@
FROM python:2
MAINTAINER "Apache CloudStack" <de...@cloudstack.apache.org>
-LABEL Vendor="Apache.org" License="ApacheV2" Version="4.10.1.0-SNAPSHOT"
+LABEL Vendor="Apache.org" License="ApacheV2" Version="4.11.0.0-SNAPSHOT"
ENV WORK_DIR=/marvin
-ENV PKG_URL=https://builds.cloudstack.org/job/build-master-marvin/lastSuccessfulBuild/artifact/tools/marvin/dist/Marvin-4.10.1.0-SNAPSHOT.tar.gz
+ENV PKG_URL=https://builds.cloudstack.org/job/build-master-marvin/lastSuccessfulBuild/artifact/tools/marvin/dist/Marvin-4.11.0.0-SNAPSHOT.tar.gz
RUN apt-get update && apt-get install -y vim
RUN pip install --upgrade paramiko nose requests
diff --git a/tools/docker/supervisord.conf b/tools/docker/supervisord.conf
index fe1575be0df..2d7ff7f2faf 100644
--- a/tools/docker/supervisord.conf
+++ b/tools/docker/supervisord.conf
@@ -8,7 +8,7 @@ autorestart=true
user=root
[program:cloudstack]
-command=/bin/bash -c "mvn -pl client jetty:run -Dsimulator"
+command=/bin/bash -c "mvn -pl client jetty:run -Dsimulator -Dorg.eclipse.jetty.annotations.maxWait=120"
directory=/root
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
diff --git a/tools/eclipse/eclipse.epf b/tools/eclipse/eclipse.epf
index b25d5553c72..6b420982cf5 100644
--- a/tools/eclipse/eclipse.epf
+++ b/tools/eclipse/eclipse.epf
@@ -428,7 +428,7 @@
/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
-/instance/org.eclipse.wst.sse.core/task-tag-projects-already-scanned=cloud-agent,cloud-api,cloud-apidoc,cloud-cli,cloud-client-ui,cloud-console-proxy,cloud-core,cloud-devcloud,cloud-devcloud-kvm,cloud-developer,cloud-engine,cloud-engine-api,cloud-engine-components-api,cloud-engine-compute,cloud-engine-network,cloud-engine-orchestration,cloud-engine-schema,cloud-engine-service,cloud-engine-storage,cloud-engine-storage-backup,cloud-engine-storage-image,cloud-engine-storage-imagemotion,cloud-engine-storage-integration-test,cloud-engine-storage-snapshot,cloud-engine-storage-volume,cloud-framework-events,cloud-framework-ipc,cloud-framework-rest,cloud-marvin,cloud-mom-rabbitmq,cloud-patches,cloud-plugin-acl-static-role-based,cloud-plugin-api-discovery,cloud-plugin-api-limit-account-based,cloud-plugin-console-proxy,cloud-plugin-example-dns-notifier,cloud-plugin-host-allocator-random,cloud-plugin-hypervisor-baremetal,cloud-plugin-hypervisor-kvm,cloud-plugin-hypervisor-ovm,cloud-plugin-hyper
visor-simulator,cloud-plugin-hypervisor-ucs,cloud-plugin-hypervisor-vmware,cloud-plugin-hypervisor-xen,cloud-plugin-netapp,cloud-plugin-network-elb,cloud-plugin-network-f5,cloud-plugin-network-netscaler,cloud-plugin-network-nvp,cloud-plugin-network-ovs,cloud-plugin-network-srx,cloud-plugin-network-bigswitch,cloud-plugin-planner-user-concentrated-pod,cloud-plugin-planner-user-dispersing,cloud-plugin-snmp-alerts,cloud-plugin-storage-allocator-random,cloud-plugin-storage-image-s3,cloud-plugin-storage-volume-default,cloud-plugin-storage-volume-solidfire,cloud-plugin-syslog-alerts,cloud-plugin-user-authenticator-ldap,cloud-plugin-user-authenticator-md5,cloud-plugin-user-authenticator-plaintext,cloud-plugin-user-authenticator-saml2,cloud-plugin-user-authenticator-sha256salted,cloud-server,cloud-testclient,cloud-tools,cloud-usage,cloud-utils,cloud-vmware-base,cloudstack,cloudstack-framework,cloudstack-plugins,xapi,cloud-framework-jobs,cloud-plugin-host-anti-affinity,cloud-plugin-network-ci
sco-vnmc,cloud-plugin-network-midonet,cloud-secondary-storage,cloudstack-services,cloud-plugin-network-internallb,cloud-plugin-planner-implicit-dedication,cloudstack-service-console-proxy
+/instance/org.eclipse.wst.sse.core/task-tag-projects-already-scanned=cloud-agent,cloud-api,cloud-apidoc,cloud-cli,cloud-client-ui,cloud-console-proxy,cloud-core,cloud-devcloud,cloud-devcloud-kvm,cloud-developer,cloud-engine,cloud-engine-api,cloud-engine-components-api,cloud-engine-compute,cloud-engine-network,cloud-engine-orchestration,cloud-engine-schema,cloud-engine-service,cloud-engine-storage,cloud-engine-storage-backup,cloud-engine-storage-image,cloud-engine-storage-imagemotion,cloud-engine-storage-integration-test,cloud-engine-storage-snapshot,cloud-engine-storage-volume,cloud-framework-events,cloud-framework-ipc,cloud-framework-rest,cloud-marvin,cloud-mom-rabbitmq,cloud-patches,cloud-plugin-acl-static-role-based,cloud-plugin-api-discovery,cloud-plugin-api-limit-account-based,cloud-plugin-console-proxy,cloud-plugin-example-dns-notifier,cloud-plugin-host-allocator-random,cloud-plugin-hypervisor-baremetal,cloud-plugin-hypervisor-kvm,cloud-plugin-hypervisor-ovm,cloud-plugin-hyper
visor-simulator,cloud-plugin-hypervisor-ucs,cloud-plugin-hypervisor-vmware,cloud-plugin-hypervisor-xen,cloud-plugin-netapp,cloud-plugin-network-elb,cloud-plugin-network-f5,cloud-plugin-network-netscaler,cloud-plugin-network-nvp,cloud-plugin-network-ovs,cloud-plugin-network-srx,cloud-plugin-network-bigswitch,cloud-plugin-planner-user-concentrated-pod,cloud-plugin-planner-user-dispersing,cloud-plugin-snmp-alerts,cloud-plugin-storage-allocator-random,cloud-plugin-storage-image-s3,cloud-plugin-storage-volume-default,cloud-plugin-storage-volume-solidfire,cloud-plugin-syslog-alerts,cloud-plugin-user-authenticator-ldap,cloud-plugin-user-authenticator-md5,cloud-plugin-user-authenticator-plaintext,cloud-plugin-user-authenticator-saml2,cloud-plugin-user-authenticator-sha256salted,cloud-server,cloud-testclient,cloud-tools,cloud-usage,cloud-utils,cloud-vmware-base,cloudstack,cloudstack-framework,cloudstack-plugins,xapi,cloud-framework-jobs,cloud-plugin-host-anti-affinity,cloud-plugin-network-ci
sco-vnmc,cloud-secondary-storage,cloudstack-services,cloud-plugin-network-internallb,cloud-plugin-planner-implicit-dedication,cloudstack-service-console-proxy
/instance/org.eclipse.jdt.debug.ui/org.eclipse.debug.ui.ExpressionView.org.eclipse.jdt.debug.ui.show_null_entries=true
/instance/org.eclipse.jdt.ui/sp_cleanup.correct_indentation=false
/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.format_source_code=true
diff --git a/tools/marvin/marvin/codegenerator.py b/tools/marvin/marvin/codegenerator.py
index 14f6d1380ae..f583d526de4 100644
--- a/tools/marvin/marvin/codegenerator.py
+++ b/tools/marvin/marvin/codegenerator.py
@@ -232,7 +232,10 @@ def finalize(self):
for cmdName in self.cmdsName:
body += self.space
- body += 'def %s(self, command, method="GET"):\n' % cmdName
+ if cmdName in ["login", "logout"]:
+ body += 'def %s(self, command, method="POST"):\n' % cmdName
+ else:
+ body += 'def %s(self, command, method="GET"):\n' % cmdName
body += self.space + self.space
body += 'response = %sResponse()\n' % cmdName
body += self.space + self.space
diff --git a/tools/marvin/marvin/codes.py b/tools/marvin/marvin/codes.py
index e23069bf94f..317cfd077bd 100644
--- a/tools/marvin/marvin/codes.py
+++ b/tools/marvin/marvin/codes.py
@@ -59,6 +59,7 @@
DISABLE = "Disable"
NETWORK_OFFERING = "network_offering"
ROOT = "ROOT"
+DATA = "DATA"
INVALID_INPUT = "INVALID INPUT"
EMPTY_LIST = "EMPTY_LIST"
FAIL = 0
diff --git a/tools/marvin/marvin/config/test_data.py b/tools/marvin/marvin/config/test_data.py
index d1ec1ba6b0e..13cd063bfa1 100644
--- a/tools/marvin/marvin/config/test_data.py
+++ b/tools/marvin/marvin/config/test_data.py
@@ -1,4 +1,4 @@
-# Licensed to the Apache Software Foundation (ASF) under one
+#t Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
@@ -674,6 +674,54 @@
"cidr": "0.0.0.0/0",
"protocol": "TCP"
},
+ "nw_off_ncc_SharedSP": {
+ "name": 'SharedSP',
+ "displaytext": 'SharedSP',
+ "guestiptype": 'Isolated',
+ "supportedservices":
+ 'Dhcp,Dns,SourceNat,Lb,StaticNat',
+ "traffictype": 'GUEST',
+ "availability": 'Optional',
+ "serviceProviderList": {
+ "Dhcp": 'VirtualRouter',
+ "Dns": 'VirtualRouter',
+ "SourceNat": 'VirtualRouter',
+ "Lb": 'Netscaler',
+ "StaticNat": 'VirtualRouter'
+ }
+ },
+ "nw_off_ncc_DedicatedSP": {
+ "name": 'DedicatedSP',
+ "displaytext": 'DedicatedSP',
+ "guestiptype": 'Isolated',
+ "supportedservices":
+ 'Dhcp,Dns,SourceNat,Lb,StaticNat',
+ "traffictype": 'GUEST',
+ "availability": 'Optional',
+ "serviceProviderList": {
+ "Dhcp": 'VirtualRouter',
+ "Dns": 'VirtualRouter',
+ "SourceNat": 'VirtualRouter',
+ "Lb": 'Netscaler',
+ "StaticNat": 'VirtualRouter'
+ }
+ },
+ "NCC": {
+ "NCCIP": '10.102.195.215',
+ },
+ "NSShared": {
+ "NSIP": '10.102.195.210',
+ },
+ "NSDedicated": {
+ "NSIP": '10.102.195.212'
+ },
+ "servicepackage_shared": {
+ "name": "SharedSP",
+ },
+ "servicepackage_dedicated": {
+ "name": "DedicatedSP",
+ },
+
"nw_off_isolated_persistent_netscaler": {
"name": 'Netscaler',
"displaytext": 'Netscaler',
@@ -731,6 +779,17 @@
"publicport": 22,
"protocol": "TCP"
},
+ "natrulerange": {
+ "privateport": 70,
+ "privateendport": 75,
+ "publicport": 70,
+ "publicendport": 75,
+ "protocol": "TCP"
+ },
+ "updatenatrulerange": {
+ "privateport": 50,
+ "privateendport": 55,
+ },
"egress_80": {
"startport": 80,
"endport": 80,
@@ -936,13 +995,6 @@
"format": "OVA",
"ostype": "Red Hat Enterprise Linux 6.0 (64-bit)"
},
- "templateregister": {
- "displaytext": "xs",
- "name": "xs",
- "passwordenabled": False,
- "url": "http://people.apache.org/~sanjeev/ttylinux_pv.vhd.bz2",
- "format": "VHD"
- },
"security_group": {"name": "custom_Sec_Grp"},
"ingress_rule": {
"protocol": "TCP",
diff --git a/tools/marvin/marvin/lib/base.py b/tools/marvin/marvin/lib/base.py
index 3283911ad83..f0af048dd21 100755
--- a/tools/marvin/marvin/lib/base.py
+++ b/tools/marvin/marvin/lib/base.py
@@ -449,7 +449,7 @@ def create(cls, apiclient, services, templateid=None, accountid=None,
hostid=None, keypair=None, ipaddress=None, mode='default',
method='GET', hypervisor=None, customcpunumber=None,
customcpuspeed=None, custommemory=None, rootdisksize=None,
- rootdiskcontroller=None):
+ rootdiskcontroller=None, macaddress=None):
"""Create the instance"""
cmd = deployVirtualMachine.deployVirtualMachineCmd()
@@ -563,6 +563,11 @@ def create(cls, apiclient, services, templateid=None, accountid=None,
if mode.lower() == 'basic':
cls.ssh_access_group(apiclient, cmd)
+ if macaddress:
+ cmd.macaddress = macaddress
+ elif macaddress in services:
+ cmd.macaddress = services["macaddress"]
+
virtual_machine = apiclient.deployVirtualMachine(cmd, method=method)
virtual_machine.ssh_ip = virtual_machine.nic[0].ipaddress
@@ -775,7 +780,7 @@ def detach_volume(self, apiclient, volume):
cmd.id = volume.id
return apiclient.detachVolume(cmd)
- def add_nic(self, apiclient, networkId, ipaddress=None):
+ def add_nic(self, apiclient, networkId, ipaddress=None, macaddress=None):
"""Add a NIC to a VM"""
cmd = addNicToVirtualMachine.addNicToVirtualMachineCmd()
cmd.virtualmachineid = self.id
@@ -784,6 +789,9 @@ def add_nic(self, apiclient, networkId, ipaddress=None):
if ipaddress:
cmd.ipaddress = ipaddress
+ if macaddress:
+ cmd.macaddress = macaddress
+
return apiclient.addNicToVirtualMachine(cmd)
def remove_nic(self, apiclient, nicId):
@@ -1097,7 +1105,7 @@ def __init__(self, items):
@classmethod
def create(cls, apiclient, volume_id, account=None,
- domainid=None, projectid=None, locationtype=None):
+ domainid=None, projectid=None, locationtype=None, asyncbackup=None):
"""Create Snapshot"""
cmd = createSnapshot.createSnapshotCmd()
cmd.volumeid = volume_id
@@ -1109,6 +1117,8 @@ def create(cls, apiclient, volume_id, account=None,
cmd.projectid = projectid
if locationtype:
cmd.locationtype = locationtype
+ if asyncbackup:
+ cmd.asyncbackup = asyncbackup
return Snapshot(apiclient.createSnapshot(cmd).__dict__)
def delete(self, apiclient):
@@ -1649,6 +1659,30 @@ def create(cls, apiclient, virtual_machine, services, ipaddressid=None,
return NATRule(apiclient.createPortForwardingRule(cmd).__dict__)
+ @classmethod
+ def update(self, apiclient, id, virtual_machine, services, fordisplay=False,
+ vmguestip=None):
+ """Create Port forwarding rule"""
+ cmd = updatePortForwardingRule.updatePortForwardingRuleCmd()
+ cmd.id = id
+
+ if "privateport" in services:
+ cmd.privateport = services["privateport"]
+
+ if "privateendport" in services:
+ cmd.privateendport = services["privateendport"]
+
+ if vmguestip:
+ cmd.vmguestip = vmguestip
+
+ if fordisplay:
+ cmd.fordisplay = fordisplay
+
+ if virtual_machine.id:
+ cmd.virtualmachineid = virtual_machine.id
+
+ return NATRule(apiclient.updatePortForwardingRule(cmd).__dict__)
+
def delete(self, apiclient):
"""Delete port forwarding"""
cmd = deletePortForwardingRule.deletePortForwardingRuleCmd()
@@ -2201,6 +2235,12 @@ def create(cls, apiclient, services, **kwargs):
cmd.ispersistent = services["ispersistent"]
if "egress_policy" in services:
cmd.egressdefaultpolicy = services["egress_policy"]
+ cmd.details = [{}]
+ if "servicepackageuuid" in services:
+ cmd.details[0]["servicepackageuuid"] = services["servicepackageuuid"]
+ if "servicepackagedescription" in services:
+ cmd.details[0]["servicepackagedescription"] = services["servicepackagedescription"]
+
cmd.availability = 'Optional'
@@ -5190,3 +5230,18 @@ def list(cls, apiclient, **kwargs):
cmd = listStorageNetworkIpRange.listStorageNetworkIpRangeCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listStorageNetworkIpRange(cmd))
+
+class RegisteredServicePackage:
+ """Manage ServicePackage registered with NCC"""
+
+ def __init__(self, items):
+ self.__dict__.update(items)
+
+ @classmethod
+ def list(cls, apiclient, **kwargs):
+ """Lists service packages published by NCC"""
+
+ cmd = listRegisteredServicePackages.listRegisteredServicePackagesCmd()
+ [setattr(cmd, k, v) for k, v in kwargs.items()]
+ return(apiclient.listRegisteredServicePackages(cmd))
+
diff --git a/tools/marvin/marvin/lib/ncc.py b/tools/marvin/marvin/lib/ncc.py
new file mode 100755
index 00000000000..5c0ae32f383
--- /dev/null
+++ b/tools/marvin/marvin/lib/ncc.py
@@ -0,0 +1,317 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""
+Base class for NCC Orchestration
+"""
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.cloudstackAPI import *
+from marvin.lib.base import Domain, Account
+from marvin.lib.utils import validateList
+from marvin.codes import PASS,FAILED
+from marvin.cloudstackException import (InvalidParameterException,
+ GetDetailExceptionInfo)
+from os import system
+from subprocess import call
+import requests, json, urllib
+
+class NCC:
+
+ def __init__(self, nccip, nsip, csip, logger=None):
+ self.nccip = nccip
+ self.nsip = nsip
+ self.csip = csip
+ self.logger = logger
+ self.__lastError = ''
+
+ def registerCCP(self, apiclient):
+ """
+ Register CCP with NCC
+ """
+ auth_keys = self.getAdminKeys(apiclient)
+ url = "http://"+self.nccip+"/cs/cca/v1/cloudstacks"
+ cs_url = "http://"+self.csip+":8080/"
+ payload = {"cloudstack": {
+ "name": "Cloudstack",
+ "apikey": auth_keys[0],
+ "secretkey": auth_keys[1],
+ "driver_username": "admin",
+ "driver_password": "nsroot",
+ "cloudstack_uri": cs_url
+ }
+ }
+ cmd_response = self.sendCmdToNCC(url, payload)
+ if cmd_response == FAILED:
+ raise Exception("Error: %s" % self.__lastError)
+
+ def registerNS(self):
+ url = "http://"+self.nccip+"/nitro/v1/config/managed_device/"
+ payload = 'object={"params":{"action":"add_device"}, "managed_device":{"ip_address":"%s",\
+ "profile_name":"ns_nsroot_profile", "sync_operation":"false"}}' % self.nsip
+ headers = {'Content-Type': 'application/x-www-form-urlencoded'}
+ cmd_response = self.sendCmdToNS(url, payload, header=headers)
+ if cmd_response == FAILED:
+ raise Exception("Error: %s" % self.__lastError)
+
+ def assignNStoCSZone(self):
+ cs_zone = self.getCSZoneFromNCC()
+ if cs_zone == FAILED:
+ raise Exception("Error: %s" % self.__lastError)
+ url = "http://"+self.nccip+"/nitro/v1/config/tag/"
+ payload = 'object={"tag": {"entity_type": "managed_device", "entity_id": "%s",\
+ "tag_key": "zone", "tag_value": "%s"}}' % (self.nsip, cs_zone)
+ header = {'Content-Type':'application/x-www-form-urlencoded'}
+ cmd_response = self.sendCmdToNS(url, payload, header=header)
+ if cmd_response == FAILED:
+ raise Exception("Error: %s" % self.__lastError)
+
+ def createServicePackages(self, name, platform_type, device_ip, isolation_policy="shared"):
+ tnt_group = self.createTenantGroup(name)
+ if tnt_group.status_code != 201:
+ raise Exception("Error: %s" % self.__lastError)
+ tnt_group_id = json.loads(tnt_group.content)["tenantgroups"][0]["id"]
+ dv_group = self.createDeviceGroup(name, platform_type)
+ if dv_group.status_code != 201:
+ raise Exception("Error: %s" % self.__lastError)
+ dv_group_id = json.loads(dv_group.content)["devicegroups"][0]["id"]
+ if isolation_policy.lower() == "shared":
+ srv_pkg = self.createServicePackageShared(name, tnt_group_id, dv_group_id, isolation_policy )
+ elif isolation_policy.lower() == "dedicated":
+ srv_pkg = self.createServicePackageDedicated(name, tnt_group_id, dv_group_id, isolation_policy )
+ else:
+ raise Exception("NS device must be either in shared or dedicated mode")
+ if srv_pkg.status_code != 201:
+ raise Exception("Error: %s" % self.__lastError)
+ dev_add_res =self.addDevicetoServicePackage(dv_group_id, device_ip)
+ if dev_add_res == FAILED:
+ raise Exception ("Error: %s" % self.__lastError)
+ srv_pkg_id = json.loads(srv_pkg.content)["servicepackages"][0]["id"]
+ publish_srv_pkg_res = self.publishServicePackage(srv_pkg_id)
+ if publish_srv_pkg_res == FAILED:
+ raise Exception("Error: %s" % self.__lastError)
+ return (dv_group_id, tnt_group_id, srv_pkg_id)
+
+ def createTenantGroup(self, name):
+ url = "http://"+self.nccip+"/admin/v1/tenantgroups"
+ payload = {"tenantgroups": [{"name": name}]}
+ res = self.sendCmdToNCC(url, payload)
+ return res
+
+ def createDeviceGroup(self, name, platform_type, device_type="netscaler"):
+ url = "http://"+self.nccip+"/admin/v1/devicegroups"
+ payload = {"devicegroups":[{"name": name,
+ "device_type": device_type,
+ "platform_type": platform_type
+ }]
+ }
+ res = self.sendCmdToNCC(url, payload)
+ return res
+
+ def createServicePackageShared(self, name, tenant_group, device_group, allocation, device_type="netscaler"):
+ url = "http://"+self.nccip+"/admin/v1/servicepackages"
+ payload = {"servicepackages":[{"allocationgroups": [{"device_type": device_type,
+ "allocationpolicy":allocation,
+ "placement_scheme": "ROUNDROBIN",
+ "deviceaffinity": "onedevice",
+ "devicegroup":{"ref": device_group}
+ }],
+ "name": name,
+ "isdefault": "false",
+ "tenantgroup": {"ref": tenant_group}
+ }]
+ }
+ res = self.sendCmdToNCC(url, payload)
+ return res
+
+ def createServicePackageDedicated(self, name, tenant_group, device_group, allocation, device_type="netscaler"):
+ url = "http://"+self.nccip+"/admin/v1/servicepackages"
+ payload = {"servicepackages":[{"allocationgroups": [{"device_type": device_type,
+ "allocationpolicy":allocation,
+ #"placement_scheme": "roundrobin or leastentity",
+ "devicegroup":{"ref": device_group}
+ }],
+ "name": name,
+ "isdefault": "false",
+ "tenantgroup": {"ref": tenant_group}
+ }]
+ }
+ res = self.sendCmdToNCC(url, payload)
+ return res
+
+ def addDevicetoServicePackage(self, devicegroup_id, device_ip):
+ url = "http://"+self.nccip+"/admin/v1/devicegroups/"+devicegroup_id+"/devices"
+ payload = {"devices":[{"ref":device_ip }]}
+ res = self.sendCmdToNCC(url, payload, method="PUT")
+ return res
+
+ def removeDevicefromServicePackage(self, devicegroup_id):
+ url = "http://"+self.nccip+"/admin/v1/devicegroups/"+devicegroup_id+"/devices"
+ payload = {"devices":[]}
+ res = self.sendCmdToNCC(url, payload, method="PUT")
+ return res
+
+ def publishServicePackage(self, pkg_id):
+ url = "http://"+self.nccip+"/cs/cca/v1/servicepackages"
+ payload = {"servicepackages":[{"servicepackageid":pkg_id}]}
+ res = self.sendCmdToNCC(url, payload)
+ return res
+
+ def getCSZoneFromNCC(self):
+ url = "http://"+self.nccip+"/cs/cca/v1/zones"
+ res = self.sendCmdToNCC(url, method="GET")
+ if res != FAILED:
+ zoneid = json.loads(res.content)["zones"][0]
+ return zoneid
+ else:
+ return FAILED
+
+ def sendCmdToNCC(self, url, payload={}, method="POST", header={'content-type': 'application/json'}):
+ try:
+ # self.logger.debug("url :%s" % url)
+ # self.logger.debug("payload: %s" % payload)
+ if method == "POST":
+ #self.logger.debug("====Sending POST Request====")
+ return self.sendPostRequstToNCC(url, payload, header)
+ if method == "GET":
+ #self.logger.debug("====Sending GET Request====")
+ return self.sendGetRequestToNCC(url, payload, header)
+ if method == "PUT":
+ return self.sendPutRequestToNCC(url, payload, header)
+ if method == "DELETE":
+ self.logger.debug("Trying delete")
+ return self.sendDeleteRequestToNCC(url, header)
+ except Exception as e:
+ self.__lastError = e
+ # self.logger.exception("sendCmdToNCC: Exception:%s" %
+ # GetDetailExceptionInfo(e))
+ return FAILED
+
+
+ def sendGetRequestToNCC(self, url, payload, header):
+ try:
+ res = requests.get(url, json=payload, auth=("nsroot", "nsroot"), headers=header)
+ return res
+ except Exception as e:
+ self.__lastError = e
+ # self.logger.exception("sendGetRequestToNCC : Exception Occured: %s" %
+ # str(self.__lastError))
+ return FAILED
+
+ def sendPostRequstToNCC(self, url, payload, header):
+ try:
+ res = requests.post(url, json=payload, auth=("nsroot", "nsroot"), headers=header)
+ return res
+ except Exception as e:
+ self.__lastError = e
+ # self.logger.exception("sendPostRequstToNCC: Exception Occured: %s" %
+ # str(self.__lastError))
+ return FAILED
+
+ def sendPutRequestToNCC(self, url, payload, header):
+ try:
+ res = requests.put(url, json=payload, auth=("nsroot", "nsroot"), headers=header)
+ return res
+ except Exception as e:
+ self.__lastError = e
+ # self.logger.exception("sendPostRequstToNCC: Exception Occured: %s" %
+ # str(self.__lastError))
+ return FAILED
+
+ def sendDeleteRequestToNCC(self, url, header):
+ try:
+ res = requests.delete (url, auth=("nsroot", "nsroot"), headers=header)
+ return res
+ except Exception as e:
+ self.__lastError = e
+ # self.logger.exception("sendPostRequstToNCC: Exception Occured: %s" %
+ # str(self.__lastError))
+ return FAILED
+
+ def sendCmdToNS(self, url, payload={}, method="POST", header={'content-type': 'application/json'}):
+ try:
+ # self.logger.debug("url :%s" % url)
+ # self.logger.debug("payload: %s" % payload)
+ if method == "POST":
+ #self.logger.debug("====Sending POST Request====")
+ return self.sendPostRequstToNS(url, payload, header)
+ if method == "GET":
+ #self.logger.debug("====Sending GET Request====")
+ return self.sendGetRequestToNS(url, payload, header)
+ except Exception as e:
+ self.__lastError = e
+ # self.logger.exception("sendCmdToNCC: Exception:%s" %
+ # GetDetailExceptionInfo(e))
+ return FAILED
+
+ def sendPostRequstToNS(self, url, payload, header):
+ try:
+ res = requests.post(url, data=payload, auth=("nsroot", "nsroot"), headers=header)
+ return res
+ except Exception as e:
+ self.__lastError = e
+ # self.logger.exception("sendPostRequstToNCC: Exception Occured: %s" %
+ # str(self.__lastError))
+ return FAILED
+
+ def sendGetRequestToNS(self, url, payload, header):
+ try:
+ res = requests.get(url, data=payload, auth=("nsroot", "nsroot"), headers=header)
+ return res
+ except Exception as e:
+ self.__lastError = e
+ # self.logger.exception("sendGetRequestToNCC : Exception Occured: %s" %
+ # str(self.__lastError))
+ return FAILED
+
+ def getAdminKeys(self, apiClient):
+ domains = Domain.list(apiClient, name="ROOT")
+ listuser = listUsers.listUsersCmd()
+ listuser.username = "admin"
+ listuser.domainid = domains[0].id
+ listuser.listall = True
+ listuserRes = apiClient.listUsers(listuser)
+ userId = listuserRes[0].id
+ apiKey = listuserRes[0].apikey
+ securityKey = listuserRes[0].secretkey
+ return [apiKey, securityKey]
+
+ def cleanup_ncc(self, device_gp_id, srv_pkg_uuid, srv_pkg_id, tnt_group_id):
+ self.removeDevicefromServicePackage(device_gp_id)
+ # Remove service package reference from Cloudplatform
+ url = "http://"+self.nccip+"/cs/cca/v1/servicepackages/"+srv_pkg_uuid
+ self.logger.debug("Sending DELETE SP uuid: %s " % url)
+ res = self.sendCmdToNCC(url, method="DELETE")
+
+
+ # Remove Service package from NCC
+ url = "http://"+self.nccip+"/admin/v1/servicepackages/"+srv_pkg_id
+ self.logger.debug("Sending DELETE SP : %s " % url)
+ res = self.sendCmdToNCC(url, method="DELETE")
+
+
+ # Remove Device group
+ url = "http://"+self.nccip+"/admin/v1/devicegroups/"+device_gp_id
+ self.logger.debug("Sending DELETE devicegroup: %s " % url)
+ res = self.sendCmdToNCC(url, method="DELETE")
+
+
+ # Remove Tenant group
+ url = "http://"+self.nccip+"/admin/v1/tenantgroups/"+tnt_group_id
+ self.logger.debug("Sending DELETE tenant group: %s " % url)
+ res = self.sendCmdToNCC(url, method="DELETE")
+ self.logger.debug("Result: %s" % res)
+ return res
diff --git a/tools/marvin/pom.xml b/tools/marvin/pom.xml
index 441f832299b..b7f3cfc1562 100644
--- a/tools/marvin/pom.xml
+++ b/tools/marvin/pom.xml
@@ -16,7 +16,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-tools</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
diff --git a/tools/marvin/setup.py b/tools/marvin/setup.py
index 6509112cd0d..347d056c45f 100644
--- a/tools/marvin/setup.py
+++ b/tools/marvin/setup.py
@@ -27,7 +27,7 @@
raise RuntimeError("python setuptools is required to build Marvin")
-VERSION = "4.10.1.0-SNAPSHOT"
+VERSION = "4.11.0.0-SNAPSHOT"
setup(name="Marvin",
version=VERSION,
@@ -57,7 +57,7 @@
"ipmisim >= 0.7"
],
extras_require={
- "nuagevsp": ["libVSD", "PyYAML", "futures", "netaddr", "retries"]
+ "nuagevsp": ["libVSD", "PyYAML", "futures", "netaddr", "retries", "jpype1"]
},
py_modules=['marvin.marvinPlugin'],
zip_safe=False,
diff --git a/tools/pom.xml b/tools/pom.xml
index f3221b735a7..5287b384a21 100644
--- a/tools/pom.xml
+++ b/tools/pom.xml
@@ -27,7 +27,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<build>
diff --git a/tools/travis/before_install.sh b/tools/travis/before_install.sh
index 7907a9cb604..409bf8a7ffd 100755
--- a/tools/travis/before_install.sh
+++ b/tools/travis/before_install.sh
@@ -23,6 +23,9 @@
echo -e "#### System Information ####"
+echo -e "\nWho am I:"
+whoami
+
echo -e "\nJava Version: "
javac -version
@@ -76,7 +79,7 @@ fi
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1397BC53640DB551
sudo sh -c 'echo "deb http://archive.ubuntu.com/ubuntu xenial main universe" >> /etc/apt/sources.list'
sudo apt-get update -q -y > /dev/null
-sudo apt-get -q -y -V install freeipmi-common libfreeipmi16 libgcrypt20 libgpg-error-dev libgpg-error0 libopenipmi0 ipmitool --no-install-recommends > /dev/null
+sudo apt-get -q -y -V install freeipmi-common libfreeipmi16 libgcrypt20 libgpg-error-dev libgpg-error0 libopenipmi0 ipmitool libpython-dev libssl-dev libffi-dev python-openssl build-essential --no-install-recommends > /dev/null
ipmitool -V
@@ -97,7 +100,7 @@ pip install --user --upgrade pip
for ((i=0;i<$RETRY_COUNT;i++))
do
- pip install --user --upgrade lxml paramiko nose texttable ipmisim > /tmp/piplog
+ pip install --user --upgrade lxml paramiko nose texttable ipmisim pyopenssl > /tmp/piplog
if [[ $? -eq 0 ]]; then
echo -e "\npython packages installed successfully"
break;
diff --git a/tools/travis/install.sh b/tools/travis/install.sh
index 61cdec00849..d759528208f 100755
--- a/tools/travis/install.sh
+++ b/tools/travis/install.sh
@@ -29,7 +29,7 @@ if [ $TEST_SEQUENCE_NUMBER -eq 1 ]; then
cd nonoss && bash -x install-non-oss.sh && cd ..
git clean -fdx .
mvn -P developer,systemvm -Dsimulator -Dnoredist --projects='org.apache.cloudstack:cloudstack' org.apache.rat:apache-rat-plugin:0.12:check
- mvn -P developer,systemvm -Dsimulator -Dnoredist clean install
+ mvn -q -B -P developer,systemvm -Dsimulator -Dnoredist clean install
else
mvn -Pdeveloper -Dsimulator clean install -DskipTests -T4 | egrep "Building|Tests|SUCCESS|FAILURE"
fi
diff --git a/tools/travis/script.sh b/tools/travis/script.sh
index 48eb3f6b688..c370225bb56 100755
--- a/tools/travis/script.sh
+++ b/tools/travis/script.sh
@@ -27,6 +27,7 @@ TESTS=($@)
echo "Running tests: " ${TESTS[@]}
for suite in "${TESTS[@]}" ; do
+ echo "Currently running test: $suite"
nosetests --with-xunit --xunit-file=integration-test-results/$suite.xml --with-marvin --marvin-config=setup/dev/advanced.cfg test/integration/$suite.py -s -a tags=advanced,required_hardware=false --zone=Sandbox-simulator --hypervisor=simulator || true ;
done
diff --git a/tools/wix-cloudstack-maven-plugin/pom.xml b/tools/wix-cloudstack-maven-plugin/pom.xml
index a04ea295c2b..2d0e81de72d 100644
--- a/tools/wix-cloudstack-maven-plugin/pom.xml
+++ b/tools/wix-cloudstack-maven-plugin/pom.xml
@@ -16,7 +16,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css
index 0477c4e9a9f..987f35d88a2 100644
--- a/ui/css/cloudstack3.css
+++ b/ui/css/cloudstack3.css
@@ -12464,6 +12464,33 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it
background-position: -70px -1311px;
}
+/*CA Cert*/
+.cacert-download {
+ display: inline-block;
+ position: relative;
+ height: 30px;
+ float: right;
+ cursor: pointer;
+ position: absolute;
+ left: 1175px;
+ top: 20px;
+}
+
+.cacert-download .icon {
+ display: inline-block;
+ float: left;
+ display: block;
+ width: 32px;
+ height: 30px;
+ background: url(../images/sprites.png) -142px -348px;
+ position: absolute;
+}
+
+.cacert-download:hover .icon,
+.cacert-download.active .icon {
+ background-position: -368px -348px;
+}
+
/*Action icons*/
.action.edit .icon {
background-position: 1px -1px;
@@ -12729,6 +12756,38 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it
background-position: -137px -614px;
}
+.blankHAForHost .icon {
+ background-position: -266px -31px;
+}
+
+.blankHAForHost:hover .icon {
+ background-position: -266px -31px;
+}
+
+.configureHAForHost .icon {
+ background-position: -270px -148px;
+}
+
+.configureHAForHost:hover .icon {
+ background-position: -270px -728px;
+}
+
+.enableHA .icon {
+ background-position: -265px -93px;
+}
+
+.enableHA:hover .icon {
+ background-position: -265px -673px;
+}
+
+.disableHA .icon {
+ background-position: -265px -120px;
+}
+
+.disableHA:hover .icon {
+ background-position: -265px -700px;
+}
+
.blankOutOfBandManagement .icon {
background-position: -266px -31px;
}
diff --git a/ui/images/sprites.png b/ui/images/sprites.png
index 0ddafaff27e..745c55cb6b2 100755
Binary files a/ui/images/sprites.png and b/ui/images/sprites.png differ
diff --git a/ui/index.html b/ui/index.html
index 41894a65f83..b94e8e5ad01 100644
--- a/ui/index.html
+++ b/ui/index.html
@@ -1837,6 +1837,7 @@ <h3><translate key="label.set.up.zone.type"/></h3>
<script type="text/javascript" src="scripts/ui-custom/projects.js"></script>
<script type="text/javascript" src="scripts/cloudStack.js"></script>
<script type="text/javascript" src="scripts/lbStickyPolicy.js"></script>
+ <script type="text/javascript" src="scripts/lbCertificatePolicy.js"></script>
<script type="text/javascript" src="scripts/ui-custom/autoscaler.js"></script>
<script type="text/javascript" src="scripts/ui-custom/healthCheck.js"></script>
<script type="text/javascript" src="scripts/autoscaler.js"></script>
@@ -1883,6 +1884,7 @@ <h3><translate key="label.set.up.zone.type"/></h3>
<script type="text/javascript" src="scripts/vm_snapshots.js"></script>
<script type="text/javascript" src="scripts/ui-custom/projectSelect.js"></script>
<script type="text/javascript" src="scripts/ui-custom/saml.js"></script>
+ <script type="text/javascript" src="scripts/ui-custom/ca.js"></script>
<script type="text/javascript" src="scripts/metrics.js"></script>
<!-- Plugin/module API -->
diff --git a/ui/l10n/ar.js b/ui/l10n/ar.js
index 6e21c628c02..538fd4b3608 100644
--- a/ui/l10n/ar.js
+++ b/ui/l10n/ar.js
@@ -20,7 +20,7 @@ var dictionary = {
"changed.item.properties": "???? ????? ??????",
"confirm.enable.s3": "???? ?? ?????? ???????? ??????? ?????? ??????? S3 ??????? ????????.",
"confirm.enable.swift": "Please fill in the following information to enable support for Swift",
- "error.could.not.change.your.password.because.ldap.is.enabled": "Error could not change your password because LDAP is enabled.",
+ "error.could.not.change.your.password.because.non.native.user": "Error could not change your password because LDAP is enabled.",
"error.could.not.enable.zone": "Could not enable zone",
"error.installWizard.message": "Something went wrong; you may go back and correct any errors",
"error.invalid.username.password": "Invalid username or password",
@@ -2176,6 +2176,7 @@ var dictionary = {
"message.restart.vpc": "???? ????? ????? ?? ????? ????? ???VPN",
"message.restart.vpc.remark": "Please confirm that you want to restart the VPC <p><small><i>Remark: making a non-redundant VPC redundant will force a clean up. The networks will not be available for a couple of minutes</i>.</small></p>",
"message.restoreVM": "Do you want to restore the VM ?",
+ "message.role.update.fail": "Failed updating rule permission",
"message.role.ordering.fail": "Reordering of rule permissions aborted as the list has changed while you were making changes. Please try again.",
"message.security.group.usage": "(Use <strong>Ctrl-click</strong> to select all applicable security groups)",
"message.select.a.zone": "A zone typically corresponds to a single datacenter. Multiple zones help make the cloud more reliable by providing physical isolation and redundancy.",
diff --git a/ui/l10n/ca.js b/ui/l10n/ca.js
index 958e2cdcc00..d97a948ef1b 100644
--- a/ui/l10n/ca.js
+++ b/ui/l10n/ca.js
@@ -20,7 +20,7 @@ var dictionary = {
"changed.item.properties": "Changed item properties",
"confirm.enable.s3": "Please fill in the following information to enable support for S3-backed Secondary Storage",
"confirm.enable.swift": "Si us plau ompliu la seg?ent informaci? per habilitar el suport per a Swift",
- "error.could.not.change.your.password.because.ldap.is.enabled": "Error could not change your password because LDAP is enabled.",
+ "error.could.not.change.your.password.because.non.native.user": "Error could not change your password because LDAP is enabled.",
"error.could.not.enable.zone": "Could not enable zone",
"error.installWizard.message": "Quelcom ha fallat, vost? pot tornar enrere i corregir els errors detalls suggerime",
"error.invalid.username.password": "Invalid username or password",
@@ -2176,6 +2176,7 @@ var dictionary = {
"message.restart.vpc": "Please confirm that you want to restart the VPC",
"message.restart.vpc.remark": "Please confirm that you want to restart the VPC <p><small><i>Remark: making a non-redundant VPC redundant will force a clean up. The networks will not be available for a couple of minutes</i>.</small></p>",
"message.restoreVM": "Do you want to restore the VM ?",
+ "message.role.update.fail": "Failed updating rule permission",
"message.role.ordering.fail": "Reordering of rule permissions aborted as the list has changed while you were making changes. Please try again.",
"message.security.group.usage": "(Use <strong>Ctrl-click</strong> to select all applicable security groups)",
"message.select.a.zone": "A zone typically corresponds to a single datacenter. Multiple zones help make the cloud more reliable by providing physical isolation and redundancy.",
diff --git a/ui/l10n/de_DE.js b/ui/l10n/de_DE.js
index fb3e110eabc..f3d93bffec5 100644
--- a/ui/l10n/de_DE.js
+++ b/ui/l10n/de_DE.js
@@ -20,7 +20,7 @@ var dictionary = {
"changed.item.properties": "Ge?nderte Eintragseigenschaften",
"confirm.enable.s3": "Bitte f?gen Sie die folgenden Informationen hinzu, um die Unterst?tzung f?r \"S3-backed Secondary Storage\" hinzuzuf?gen",
"confirm.enable.swift": "Bitte f?gen Sie die folgenden Informationen hinzu, um die Unterst?tzung f?r Swift zu erm?glichen.",
- "error.could.not.change.your.password.because.ldap.is.enabled": "Fehler! Ihr Passwort konnte nicht ge?ndert werden, weil LDAP konfiguriert wurde.",
+ "error.could.not.change.your.password.because.non.native.user": "Fehler! Ihr Passwort konnte nicht ge?ndert werden, weil LDAP konfiguriert wurde.",
"error.could.not.enable.zone": "Zone konnte nicht aktiviert werden",
"error.installWizard.message": "Etwas ging schief; Sie k?nnen zur?ckgehen um m?gliche Fehler zu beheben",
"error.invalid.username.password": "Ung?ltiger Benutzername oder ung?ltiges Passwort",
@@ -2176,6 +2176,7 @@ var dictionary = {
"message.restart.vpc": "Bitte best?tigen Sie, dass Sie den VPC neu starten m?chten",
"message.restart.vpc.remark": "Bitte best?tigen Sie, dass Sie die VPC neu starten m?chten <p>small><i>Hinweis: Ein nicht-redundante VPC redundant zu machen wird eine Bereinigung erzwingen. Die Netzwerke werden dadurch einige Minuten nicht verf?gbar sein</i>.</small></p>",
"message.restoreVM": "M?chten Sie die VM wiederherstellen?",
+ "message.role.update.fail": "Failed updating rule permission",
"message.role.ordering.fail": "Die Neuordnung der Regelberechtigungen wurde abgebrochen, es sind ?nderungen eingetreten w?hrend Sie an der Liste Arbeiten durchgef?hrt haben. Bitte versuchen Sie es erneut.",
"message.security.group.usage": "(Verwenden Sie <strong>Ctrl-click</strong> um alle passenden Sicherheits Gruppen auszuw?hlen)",
"message.select.a.zone": "Eine Zone steht typischerweise f?r ein einzelnes Rechenzentrum. Mehrere Zonen helfen dabei, die Cloud zuverl?ssiger zu machen durch physikalische Isolation und Redundanz.",
diff --git a/ui/l10n/en.js b/ui/l10n/en.js
index c71c7c103aa..3727dc6a313 100644
--- a/ui/l10n/en.js
+++ b/ui/l10n/en.js
@@ -19,7 +19,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
"changed.item.properties":"Changed item properties",
"confirm.enable.s3":"Please fill in the following information to enable support for S3-backed Secondary Storage",
"confirm.enable.swift":"Please fill in the following information to enable support for Swift",
-"error.could.not.change.your.password.because.ldap.is.enabled":"Error could not change your password because LDAP is enabled.",
+"error.could.not.change.your.password.because.non.native.user":"Error could not change your password because user is not a native CloudStack user.",
"error.could.not.enable.zone":"Could not enable zone",
"error.installWizard.message":"Something went wrong; you may go back and correct any errors",
"error.invalid.username.password":"Invalid username or password",
@@ -45,6 +45,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
"image.directory":"Image Directory",
"inline":"Inline",
"instances.actions.reboot.label":"Reboot instance",
+"label.async.backup":"Async Backup",
"label.CIDR.list":"CIDR list",
"label.CIDR.of.destination.network":"CIDR of destination network",
"label.CPU.cap":"CPU Cap",
@@ -254,6 +255,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
"label.action.reboot.systemvm.processing":"Rebooting System VM....",
"label.action.recurring.snapshot":"Recurring Snapshots",
"label.action.register.iso":"Register ISO",
+"label.action.register.ncc":"Register NCC",
"label.action.register.template":"Register Template from URL",
"label.action.release.ip":"Release IP",
"label.action.release.ip.processing":"Releasing IP....",
@@ -318,6 +320,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
"label.add.by":"Add by",
"label.add.by.cidr":"Add By CIDR",
"label.add.by.group":"Add By Group",
+"label.add.certificate":"Add Certificate",
"label.add.ciscoASA1000v":"Add CiscoASA1000v Resource",
"label.add.cluster":"Add Cluster",
"label.add.compute.offering":"Add compute offering",
@@ -425,6 +428,8 @@ var dictionary = {"ICMP.code":"ICMP Code",
"label.allocated":"Allocated",
"label.allocation.state":"Allocation State",
"label.allow":"Allow",
+"label.annotated.by":"Annotator",
+"label.annotation":"Annotation",
"label.anti.affinity":"Anti-affinity",
"label.anti.affinity.group":"Anti-affinity Group",
"label.anti.affinity.groups":"Anti-affinity Groups",
@@ -502,6 +507,10 @@ var dictionary = {"ICMP.code":"ICMP Code",
"label.capacity.bytes":"Capacity Bytes",
"label.capacity.iops":"Capacity IOPS",
"label.certificate":"Server certificate",
+"label.certificate.details":"Certificate Details",
+"label.certificate.name":"Certificate",
+"label.certificateid":"Certificate ID",
+"label.chain":"Chain",
"label.change.affinity":"Change Affinity",
"label.change.ipaddress":"Change IP address for NIC",
"label.change.service.offering":"Change service offering",
@@ -617,6 +626,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
"label.delete.project":"Delete project",
"label.delete.role":"Delete Role",
"label.delete.secondary.staging.store":"Delete Secondary Staging Store",
+"label.delete.sslcertificate":"Delete SSL Certificate",
"label.delete.ucs.manager":"Delete UCS Manager",
"label.delete.vpn.user":"Delete VPN user",
"label.deleting.failed":"Deleting Failed",
@@ -751,6 +761,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
"label.firewall":"Firewall",
"label.first.name":"First Name",
"label.firstname.lower":"firstname",
+"label.forged.transmits":"Forged Transmits",
"label.format":"Format",
"label.format.lower":"format",
"label.friday":"Friday",
@@ -801,6 +812,12 @@ var dictionary = {"ICMP.code":"ICMP Code",
"label.guest.traffic.vswitch.type":"Guest Traffic vSwitch Type",
"label.guest.type":"Guest Type",
"label.ha.enabled":"HA Enabled",
+"label.ha.configure":"Configure HA",
+"label.ha.disable":"Disable HA",
+"label.ha.enable":"Enable HA",
+"label.ha.provider":"HA Provider",
+"label.ha.state":"HA State",
+"label.ha":"HA",
"label.health.check":"Health Check",
"label.health.check.advanced.options":"Advanced Options:",
"label.health.check.configurations.options":"Configuration Options:",
@@ -931,6 +948,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
"label.lang.polish":"Polish",
"label.lang.russian":"Russian",
"label.lang.spanish":"Spanish",
+"label.last.annotated":"Last annotation date",
"label.last.disconnected":"Last Disconnected",
"label.last.name":"Last Name",
"label.lastname.lower":"lastname",
@@ -941,6 +959,10 @@ var dictionary = {"ICMP.code":"ICMP Code",
"label.lb.algorithm.leastconn":"Least connections",
"label.lb.algorithm.roundrobin":"Round-robin",
"label.lb.algorithm.source":"Source",
+"label.lb.protocol.http":"HTTP",
+"label.lb.protocol.ssl":"SSL",
+"label.lb.protocol.tcp":"TCP",
+"label.lb.protocol.udp":"UDP",
"label.ldap.configuration":"LDAP Configuration",
"label.ldap.group.name":"LDAP Group",
"label.ldap.link.type":"Type",
@@ -970,6 +992,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
"label.management":"Management",
"label.management.ips":"Management IP Addresses",
"label.management.server":"Management Server",
+"label.mac.address.changes":"MAC Address Changes",
"label.max.cpus":"Max. CPU cores",
"label.max.guest.limit":"Max guest limit",
"label.max.instances":"Max Instances",
@@ -1101,9 +1124,14 @@ var dictionary = {"ICMP.code":"ICMP Code",
"label.name.lower":"name",
"label.name.optional":"Name (Optional)",
"label.nat.port.range":"NAT Port Range",
+"label.ncc":"NCC",
+"label.ncc.delete":"Delete NCC",
+"label.ncc.details":"NCC Details",
"label.netScaler":"NetScaler",
"label.netmask":"Netmask",
"label.netscaler.details":"NetScaler details",
+"label.netscaler.service.packages":"Netscaler Service Packages",
+"label.netscaler.service.packages.description":"Service Package Description",
"label.network":"Network",
"label.network.ACL":"Network ACL",
"label.network.ACL.total":"Network ACL Total",
@@ -1263,6 +1291,8 @@ var dictionary = {"ICMP.code":"ICMP Code",
"label.private.port":"Private Port",
"label.private.zone":"Private Zone",
"label.privatekey":"PKCS#8 Private Key",
+"label.privatekey.name":"Private Key",
+"label.privatekey.password":"Private Key Password",
"label.profile":"Profile",
"label.project":"Project",
"label.project.dashboard":"Project dashboard",
@@ -1271,6 +1301,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
"label.project.name":"Project name",
"label.project.view":"Project View",
"label.projects":"Projects",
+"label.promiscuous.mode":"Promiscuous Mode",
"label.protocol":"Protocol",
"label.protocol.number":"Protocol Number",
"label.provider":"Provider",
@@ -1520,6 +1551,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
"label.ssh.key.pair":"SSH Key Pair",
"label.ssh.key.pair.details":"SSH Key Pair Details",
"label.ssh.key.pairs":"SSH Key Pairs",
+"label.sslcertificates":"SSL Certificates",
"label.standard.us.keyboard":"Standard (US) keyboard",
"label.start.IP":"Start IP",
"label.start.lb.vm":"Start LB VM",
@@ -1667,6 +1699,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
"label.username":"Username",
"label.username.lower":"username",
"label.users":"Users",
+"label.uuid":"UUID",
"label.vSwitch.type":"vSwitch Type",
"label.value":"Value",
"label.vcdcname":"vCenter DC name",
@@ -1757,6 +1790,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
"label.vpn":"VPN",
"label.vpn.customer.gateway":"VPN Customer Gateway",
"label.vpn.force.encapsulation":"Force UDP Encapsulation of ESP Packets",
+"label.vpn.users":"VPN Users",
"label.vsmctrlvlanid":"Control VLAN ID",
"label.vsmpktvlanid":"Packet VLAN ID",
"label.vsmstoragevlanid":"Storage VLAN ID",
@@ -1827,6 +1861,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
"message.action.delete.template":"Please confirm that you want to delete this template.",
"message.action.delete.template.for.all.zones":"The template is used by all zones. Please confirm that you want to delete it from all zones.",
"message.action.delete.volume":"Please confirm that you want to delete this volume.",
+"message.action.delete.vpn.user":"Please confirm that you want to delete the VPN user.",
"message.action.delete.zone":"Please confirm that you want to delete this zone.",
"message.action.destroy.instance":"Please confirm that you want to destroy this instance.",
"message.action.destroy.systemvm":"Please confirm that you want to destroy this System VM.",
@@ -2020,6 +2055,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
"message.delete.affinity.group":"Please confirm that you would like to remove this affinity group.",
"message.delete.gateway":"Please confirm you want to delete the gateway",
"message.delete.project":"Are you sure you want to delete this project?",
+"message.delete.sslcertificate":"Please confirm that you would like to delete this certificate.",
"message.delete.user":"Please confirm that you would like to delete this user.",
"message.desc.add.new.lb.sticky.rule":"Add new LB sticky rule",
"message.desc.advanced.zone":"For more sophisticated network topologies. This network model provides the most flexibility in defining guest networks and providing custom network offerings such as firewall, VPN, or load balancer support.",
@@ -2056,6 +2092,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
"message.enable.vpn.access":"VPN is currently disabled for this IP Address. Would you like to enable VPN access?",
"message.enabled.vpn":"Your Remote Access VPN is currently enabled and can be accessed via the IP",
"message.enabled.vpn.ip.sec":"Your IPSec pre-shared key is",
+"message.enabled.vpn.note":"Note: VPN users are now accessed by changing views at the networks tab.",
"message.enabling.network.offering":"Enabling network offering",
"message.enabling.security.group.provider":"Enabling Security Group provider",
"message.enabling.vpc.offering":"Enabling VPC offering",
@@ -2122,6 +2159,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
"message.migrate.router.confirm":"Please confirm the host you wish to migrate the router to:",
"message.migrate.systemvm.confirm":"Please confirm the host you wish to migrate the system VM to:",
"message.migrate.volume":"Please confirm that you want to migrate volume to another primary storage.",
+"message.ncc.delete.confirm":"Please confirm you want to delete this NCC",
"message.network.addVM.desc":"Please specify the network that you would like to add this VM to. A new NIC will be added for this network.",
"message.network.addVMNIC":"Please confirm that you would like to add a new VM NIC for this network.",
"message.network.remote.access.vpn.configuration":"Remote Access VPN configuration has been generated, but it failed to apply. Please check connectivity of the network element, then re-try.",
@@ -2165,6 +2203,8 @@ var dictionary = {"ICMP.code":"ICMP Code",
"message.read.admin.guide.scaling.up":"Please read the dynamic scaling section in the admin guide before scaling up.",
"message.recover.vm":"Please confirm that you would like to recover this VM.",
"message.redirecting.region":"Redirecting to region...",
+"message.register.failed":"Registration Failed",
+"message.register.succeeded":"Registration Succeeded",
"message.reinstall.vm":"NOTE: Proceed with caution. This will cause the VM to be reinstalled from the template; data on the root disk will be lost. Extra data volumes, if any, will not be touched.",
"message.remove.ldap":"Are you sure you want to delete the LDAP configuration?",
"message.remove.region":"Are you sure you want to remove this region from this management server?",
@@ -2180,6 +2220,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
"message.restart.vpc":"Please confirm that you want to restart the VPC",
"message.restart.vpc.remark":"Please confirm that you want to restart the VPC <p><small><i>Remark: making a non-redundant VPC redundant will force a clean up. The networks will not be available for a couple of minutes</i>.</small></p>",
"message.restoreVM":"Do you want to restore the VM ?",
+"message.role.update.fail": "Failed updating rule permission",
"message.role.ordering.fail":"Reordering of rule permissions aborted as the list has changed while you were making changes. Please try again.",
"message.security.group.usage":"(Use <strong>Ctrl-click</strong> to select all applicable security groups)",
"message.select.a.zone":"A zone typically corresponds to a single datacenter. Multiple zones help make the cloud more reliable by providing physical isolation and redundancy.",
@@ -2249,6 +2290,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
"message.vnmc.available.list":"VNMC is not available from provider list.",
"message.vnmc.not.available.list":"VNMC is not available from provider list.",
"message.volume.create.template.confirm":"Please confirm that you wish to create a template for this disk volume. Creation of the template can range from several minutes to longer depending on the size of the volume.",
+"message.volume.root.shrink.disk.size" :"Shrink operation on ROOT volume not supported",
"message.waiting.for.builtin.templates.to.load":"Waiting for builtin templates to load...",
"message.you.must.have.at.least.one.physical.network":"You must have at least one physical network",
"message.your.cloudstack.is.ready":"Your CloudStack is ready!",
diff --git a/ui/l10n/es.js b/ui/l10n/es.js
index c311cd4853d..38ec9c00ac2 100644
--- a/ui/l10n/es.js
+++ b/ui/l10n/es.js
@@ -20,7 +20,7 @@ var dictionary = {
"changed.item.properties": "Cambiadas las propiedades del elemento",
"confirm.enable.s3": "Por favor, complete la siguiente informaci?n para habilitar el soporte del Almacenamiento Secundario sobre S3",
"confirm.enable.swift": "Por favor, complete la siguiente informaci?n para habilitar el soporte para Swift",
- "error.could.not.change.your.password.because.ldap.is.enabled": "Error, no se puede cambiar la contrase?a porque LDAP esta activado",
+ "error.could.not.change.your.password.because.non.native.user": "Error, no se puede cambiar la contrase?a porque LDAP esta activado",
"error.could.not.enable.zone": "No se pudo habilitar la zona",
"error.installWizard.message": "Algo salio mal, debes ir para atr?s y corregir los errores.",
"error.invalid.username.password": "Usuario o contrase?a invalido",
@@ -2176,6 +2176,7 @@ var dictionary = {
"message.restart.vpc": "Por favor confirme que usted quiere reiniciar el VPC",
"message.restart.vpc.remark": "Por favor confirme que desea reiniciar el VPC <p><small><i>Atenci?n: creando un VPC sin redundancia forzara la limpieza. Todas las redes dejaran de estar disponibles por unos minutos</i>.</small></p>",
"message.restoreVM": "?Desea recuperar la MV?",
+ "message.role.update.fail": "Failed updating rule permission",
"message.role.ordering.fail": "Reordenaci?n de permisos de reglas abortada ya que la lista ha cambiado mientras realizaba los cambios. Por favor, intente de nuevo. ",
"message.security.group.usage": "(Use <strong> Ctrl-click </strong> para seleccionar todos los grupos de seguridad pertinentes)",
"message.select.a.zone": "Una zona normalmente se corresponde con un solo datacenter. M?ltiples zonas pueden ayudar a aumentar la disponibilidad del cloud al proveer aislamiento f?sico y redundancia.",
diff --git a/ui/l10n/fr_FR.js b/ui/l10n/fr_FR.js
index 18b5b43a685..0bb6a0dc8c9 100644
--- a/ui/l10n/fr_FR.js
+++ b/ui/l10n/fr_FR.js
@@ -20,7 +20,7 @@ var dictionary = {
"changed.item.properties": "Propri?t?s de l'?l?ment modifi?es",
"confirm.enable.s3": "Remplir les informations suivantes pour activer le support de stockage secondaire S3",
"confirm.enable.swift": "Remplir les informations suivantes pour activer Swift",
- "error.could.not.change.your.password.because.ldap.is.enabled": "Erreur: impossible de changer votre mot de passe car le mode LDAP est activ?.",
+ "error.could.not.change.your.password.because.non.native.user": "Erreur: impossible de changer votre mot de passe car le mode LDAP est activ?.",
"error.could.not.enable.zone": "Impossible d'activer la zone",
"error.installWizard.message": "Une erreur s'est produite ; vous pouvez retourner en arri?re et corriger les erreurs",
"error.invalid.username.password": "Identifiant ou mot de passe invalide",
@@ -2176,6 +2176,7 @@ var dictionary = {
"message.restart.vpc": "Confirmer le red?marrage du VPC",
"message.restart.vpc.remark": "Veuillez confirmer que vous voulez red?marrer le VPC <p><small><i>Note : transformer un VPC non-redondant en VPC redondant va forcer un nettoyage du routeur. Le r?seau associ? ne sera pas disponible durant quelques minutes</i>.</small></p>",
"message.restoreVM": "Voulez-vous restaurer la VM ?",
+ "message.role.update.fail": "Failed updating rule permission",
"message.role.ordering.fail": "La r?organisation des r?gles d'autorisations a ?t? abandonn?e car la liste a chang? pendant que vous apportez des modifications. Veuillez r?essayer.",
"message.security.group.usage": "(Utilisez <strong>Ctrl-clic</strong> pour s?lectionner les groupes de s?curit? vis?s)",
"message.select.a.zone": "Une zone correspond typiquement ? un seul centre de donn?es. Des zones multiples peuvent permettre de rendre votre cloud plus fiable en apportant une isolation physique et de la redondance.",
diff --git a/ui/l10n/hu.js b/ui/l10n/hu.js
index d884fc29fdd..3da69417fca 100644
--- a/ui/l10n/hu.js
+++ b/ui/l10n/hu.js
@@ -20,7 +20,7 @@ var dictionary = {
"changed.item.properties": "Az elem tulajdons?gai megv?ltoztak",
"confirm.enable.s3": "T?ltsd ki a k?vetkez? inform?ci?kat az S3 m?sodlagos t?r bekapcsol?s?hoz!",
"confirm.enable.swift": "T?ltsd ki a k?vetkez? inform?ci?kat a Swift t?mogat?s bekapcsol?s?hoz!",
- "error.could.not.change.your.password.because.ldap.is.enabled": "Nem siker?lt megv?ltoztatni a jelszavadat, mert az LDAP be van kapcsolva.",
+ "error.could.not.change.your.password.because.non.native.user": "Nem siker?lt megv?ltoztatni a jelszavadat, mert az LDAP be van kapcsolva.",
"error.could.not.enable.zone": "A z?na enged?lyez?se sikertelen",
"error.installWizard.message": "Valami nem siker?lt, visszamehetsz kijav?tani a hib?kat.",
"error.invalid.username.password": "?rv?nytelen felhaszn?l?n?v vagy jelsz?",
@@ -2176,6 +2176,7 @@ var dictionary = {
"message.restart.vpc": "Er?s?tsd meg, hogy ?jra akarod ind?tani a VPC-t!",
"message.restart.vpc.remark": "Er?s?tsd meg, hogy ?jra akarod ind?tani a VPC-t! <p><small><i>Megjegyz?s: egy nem redund?ns VPC redund?nss? t?tele takar?t?st tesz sz?ks?gess?. A h?l?zatok nem lesznek el?rhet?ek egy p?r percig.</i>.</small></p>",
"message.restoreVM": "Helyre akarod ?ll?tani a VM-et?",
+ "message.role.update.fail": "Failed updating rule permission",
"message.role.ordering.fail": "Reordering of rule permissions aborted as the list has changed while you were making changes. Please try again.",
"message.security.group.usage": "(A <strong>Ctrl-kattint?s</strong> haszn?lat?val tudod az ?sszes alkalmazhat? biztons?gi csoportot kiv?lasztani)",
"message.select.a.zone": "Egy z?na tipikusan egy adatk?zpontnak felel meg. T?bb z?na seg?thet a felh?t megb?zhat?bb? tenni fizikai izol?ci?val ?s redundanci?val.",
diff --git a/ui/l10n/it_IT.js b/ui/l10n/it_IT.js
index 3ce6caff823..247b8e04a73 100644
--- a/ui/l10n/it_IT.js
+++ b/ui/l10n/it_IT.js
@@ -20,7 +20,7 @@ var dictionary = {
"changed.item.properties": "Elementi delle propriet? modificati",
"confirm.enable.s3": "Si prega di inserire i valori richiesti per abilitare il supporto per il Secondary Storage di tipo S3",
"confirm.enable.swift": "Si prega di inserire i valori richiesti per abilitare il supporto per Swift",
- "error.could.not.change.your.password.because.ldap.is.enabled": "Errore non ? possibile cambiare la tua password perch? LDAP ? abilitato.",
+ "error.could.not.change.your.password.because.non.native.user": "Errore non ? possibile cambiare la tua password perch? LDAP ? abilitato.",
"error.could.not.enable.zone": "Impossibile abilitare la zona",
"error.installWizard.message": "E' stato rilevato un errore: tornare agli step precedenti e correggere gli errori",
"error.invalid.username.password": "Username o Password non valida",
@@ -2176,6 +2176,7 @@ var dictionary = {
"message.restart.vpc": "Si prega di confermare di voler riavviare VPC",
"message.restart.vpc.remark": "Please confirm that you want to restart the VPC <p><small><i>Remark: making a non-redundant VPC redundant will force a clean up. The networks will not be available for a couple of minutes</i>.</small></p>",
"message.restoreVM": "Do you want to restore the VM ?",
+ "message.role.update.fail": "Failed updating rule permission",
"message.role.ordering.fail": "Reordering of rule permissions aborted as the list has changed while you were making changes. Please try again.",
"message.security.group.usage": "(Use <strong>Ctrl-click</strong> to select all applicable security groups)",
"message.select.a.zone": "Una zona corrisponde tipicamente ad un singolo datacenter. Zone multiple consentono di aumentare l'affidabilit? creando isolamento fisico e ridondanza.",
diff --git a/ui/l10n/ja_JP.js b/ui/l10n/ja_JP.js
index 797b351358e..a5da1a37d77 100644
--- a/ui/l10n/ja_JP.js
+++ b/ui/l10n/ja_JP.js
@@ -20,7 +20,7 @@ var dictionary = {
"changed.item.properties": "???????????",
"confirm.enable.s3": "S3 ????????? ?????????????????????????????????",
"confirm.enable.swift": "Swift ????????????????????????????",
- "error.could.not.change.your.password.because.ldap.is.enabled": "????LDAP ????????????????????",
+ "error.could.not.change.your.password.because.non.native.user": "????LDAP ????????????????????",
"error.could.not.enable.zone": "???????????????",
"error.installWizard.message": "????????????????????????",
"error.invalid.username.password": "???????????????????",
@@ -2180,6 +2180,7 @@ var dictionary = {
"message.restart.vpc": "VPC ???????????????",
"message.restart.vpc.remark": "VPC ??????????????? <p><small><i>??: ??? VPC ????????????????????. ???????????????????????</i>.</small></p>",
"message.restoreVM": "VM ??????????????",
+ "message.role.update.fail": "Failed updating rule permission",
"message.role.ordering.fail": "Reordering of rule permissions aborted as the list has changed while you were making changes. Please try again.",
"message.security.group.usage": "(?????????? ???????????????<strong>Ctrl ????????????</strong>??????)",
"message.select.a.zone": "???????????????????????????????????????????????????????????????????????",
diff --git a/ui/l10n/ko_KR.js b/ui/l10n/ko_KR.js
index 5cd6d12639f..f592a7c1c87 100644
--- a/ui/l10n/ko_KR.js
+++ b/ui/l10n/ko_KR.js
@@ -20,7 +20,7 @@ var dictionary = {
"changed.item.properties": "?? ?? ??",
"confirm.enable.s3": "S3 ?? 2? ??? ??? ??? ?? ??? ??? ????.",
"confirm.enable.swift": "Swift ?? ??? ?? ??? ?? ??? ??? ????.",
- "error.could.not.change.your.password.because.ldap.is.enabled": "LDAP ??? ??? ?? ?? ??? ???? ??? ???????.",
+ "error.could.not.change.your.password.because.non.native.user": "LDAP ??? ??? ?? ?? ??? ???? ??? ???????.",
"error.could.not.enable.zone": "Zone? ?? ? ? ????.",
"error.installWizard.message": "??? ??????. ?? ??? ??? ? ????.",
"error.invalid.username.password": "???? ?? ???? ?? ??",
@@ -2176,6 +2176,7 @@ var dictionary = {
"message.restart.vpc": "VPC? ??????????",
"message.restart.vpc.remark": "Please confirm that you want to restart the VPC <p><small><i>Remark: making a non-redundant VPC redundant will force a clean up. The networks will not be available for a couple of minutes</i>.</small></p>",
"message.restoreVM": "Do you want to restore the VM ?",
+ "message.role.update.fail": "Failed updating rule permission",
"message.role.ordering.fail": "Reordering of rule permissions aborted as the list has changed while you were making changes. Please try again.",
"message.security.group.usage": "(???? ?? ??? ?? ????? <strong>Ctrl ?? ???? ??</strong>? ????)",
"message.select.a.zone": "Zone? ?? ?? ??? ??? ?????. ?? Zone? ???? ????? ???? ???? ????? ???? ?? ? ????.",
diff --git a/ui/l10n/nb_NO.js b/ui/l10n/nb_NO.js
index 7304a1162ac..1ef414572c4 100644
--- a/ui/l10n/nb_NO.js
+++ b/ui/l10n/nb_NO.js
@@ -20,7 +20,7 @@ var dictionary = {
"changed.item.properties": "Endrede egenskaper",
"confirm.enable.s3": "Vennligst fyll inn f?lgende informasjon for ? aktivere st?tte for S3-st?ttet sekund?rlagring",
"confirm.enable.swift": "Vennligst fyll inn f?lgende informasjon for ? aktivere st?tte for Swift",
- "error.could.not.change.your.password.because.ldap.is.enabled": "Feil kunne ikke bytte ditt passord fordi LDAP er aktivert.",
+ "error.could.not.change.your.password.because.non.native.user": "Feil kunne ikke bytte ditt passord fordi LDAP er aktivert.",
"error.could.not.enable.zone": "Kunne ikke aktivere sonen",
"error.installWizard.message": "Noe gikk galt. G? tilbake og korriger feilene.",
"error.invalid.username.password": "Ugyldig brukernavn eller passord",
@@ -2176,6 +2176,7 @@ var dictionary = {
"message.restart.vpc": "Vennligst bekreft at du ?nsker ? restarte VPC",
"message.restart.vpc.remark": "Vennligst bekreft du at du vil restarte VPC <p><small><i>Merk: ? gj?re en ikke reduntant VPC redundant vil tvinge en opprydning. Nettverkene vil ikke v?re tilgjengelig i noen minutter</i>.</small></p>",
"message.restoreVM": "Vil du gjenopprette denne VMen?",
+ "message.role.update.fail": "Failed updating rule permission",
"message.role.ordering.fail": "Reordering of rule permissions aborted as the list has changed while you were making changes. Please try again.",
"message.security.group.usage": "(Bruk <strong>Ctrl-klikk</strong> for ? velge alle aktuelle sikkerhetsgrupper)",
"message.select.a.zone": "En sone er typisk sett p? som et datasenter. Multiple soner gir CloudStack bedre p?litelighet gjennom isolasjon og redundans.",
diff --git a/ui/l10n/nl_NL.js b/ui/l10n/nl_NL.js
index ccf27ccc336..58465f377d4 100644
--- a/ui/l10n/nl_NL.js
+++ b/ui/l10n/nl_NL.js
@@ -20,7 +20,7 @@ var dictionary = {
"changed.item.properties": "Item eigenschappen gewijzigd",
"confirm.enable.s3": "Vul de volgende informatie in om ondersteuning voor S3-aangestuurde Secundaire Opslag te activeren",
"confirm.enable.swift": "Vul de volgende informatie in om ondersteuning voor Swift te activeren",
- "error.could.not.change.your.password.because.ldap.is.enabled": "Fout. Kan wachtwoord niet wijzigen omdat LDAP is uitgeschakeld.",
+ "error.could.not.change.your.password.because.non.native.user": "Fout. Kan wachtwoord niet wijzigen omdat LDAP is uitgeschakeld.",
"error.could.not.enable.zone": "Kon zone niet activeren",
"error.installWizard.message": "Er ging iets mis; je kunt teruggaan om de eventuele fouten te herstellen",
"error.invalid.username.password": "Ongeldige gebruikersnaam of wachtwoord",
@@ -2176,6 +2176,7 @@ var dictionary = {
"message.restart.vpc": "Bevestig dat u deze VPC wilt herstarten",
"message.restart.vpc.remark": "Bevestig altublieft dat U de VPC wilt herstarten <p><small><i>Opmerking: Een niet-redundante VPC redundant maken zal opschonen forceren. De netwerken zullen enige tijd niet beschikbaar zijn</i>.</small></p>",
"message.restoreVM": "Wilt u de VM herstellen?",
+ "message.role.update.fail": "Failed updating rule permission",
"message.role.ordering.fail": "Reordering of rule permissions aborted as the list has changed while you were making changes. Please try again.",
"message.security.group.usage": "(Gebruik <strong>Ctrl-klik</strong> om meerdere security groups te selecteren)",
"message.select.a.zone": "Een zone correspondeert meestal met een enkel datacenter. Meerdere zones maken de cloud betrouwbaarder door fysiek isolatie en redunatie te verzorgen.",
diff --git a/ui/l10n/pl.js b/ui/l10n/pl.js
index bd2e3a3728d..1ba89b25cc1 100644
--- a/ui/l10n/pl.js
+++ b/ui/l10n/pl.js
@@ -20,7 +20,7 @@ var dictionary = {
"changed.item.properties": "Changed item properties",
"confirm.enable.s3": "Please fill in the following information to enable support for S3-backed Secondary Storage",
"confirm.enable.swift": "Please fill in the following information to enable support for Swift",
- "error.could.not.change.your.password.because.ldap.is.enabled": "Error could not change your password because LDAP is enabled.",
+ "error.could.not.change.your.password.because.non.native.user": "Error could not change your password because LDAP is enabled.",
"error.could.not.enable.zone": "Could not enable zone",
"error.installWizard.message": "Something went wrong; you may go back and correct any errors",
"error.invalid.username.password": "B??dna nazwa u?ytkownika lub has?o",
@@ -2176,6 +2176,7 @@ var dictionary = {
"message.restart.vpc": "Please confirm that you want to restart the VPC",
"message.restart.vpc.remark": "Please confirm that you want to restart the VPC <p><small><i>Remark: making a non-redundant VPC redundant will force a clean up. The networks will not be available for a couple of minutes</i>.</small></p>",
"message.restoreVM": "Do you want to restore the VM ?",
+ "message.role.update.fail": "Failed updating rule permission",
"message.role.ordering.fail": "Reordering of rule permissions aborted as the list has changed while you were making changes. Please try again.",
"message.security.group.usage": "(Use <strong>Ctrl-click</strong> to select all applicable security groups)",
"message.select.a.zone": "A zone typically corresponds to a single datacenter. Multiple zones help make the cloud more reliable by providing physical isolation and redundancy.",
diff --git a/ui/l10n/pt_BR.js b/ui/l10n/pt_BR.js
index 8d0198bb727..77bfe53eed1 100644
--- a/ui/l10n/pt_BR.js
+++ b/ui/l10n/pt_BR.js
@@ -20,7 +20,7 @@ var dictionary = {
"changed.item.properties": "Propriedades do item alteradas",
"confirm.enable.s3": "Por favor, preencha as informa??es abaixo para habilitar suporte o Storage Secund?rio fornecido por S3",
"confirm.enable.swift": "Por favor, preencha as informa??es abaixo para habilitar suporte ao Swift",
- "error.could.not.change.your.password.because.ldap.is.enabled": "Erro: a nuvem n?o alterou sua senha porque o LDAP est? ativo.",
+ "error.could.not.change.your.password.because.non.native.user": "Erro: a nuvem n?o alterou sua senha porque o LDAP est? ativo.",
"error.could.not.enable.zone": "N?o foi poss?vel habilitar a zona",
"error.installWizard.message": "Alguma coisa est? errada; voc? pode voltar e corrigir quaisquer erros",
"error.invalid.username.password": "Usu?rio ou senha inv?lidos",
@@ -2176,6 +2176,7 @@ var dictionary = {
"message.restart.vpc": "Favor confirmar que voc? deseja reiniciar a VPC",
"message.restart.vpc.remark": "Por favor, confirme a reinicializa??o do VPC <p><small><i>Observa??o: fazendo um VPC redundante n?o redundante ir? for?ar uma limpeza. As redes n?o estar?o dispon?veis por alguns minutos</i>.</small></p>",
"message.restoreVM": "Quer restaurar a VM?",
+ "message.role.update.fail": "Failed updating rule permission",
"message.role.ordering.fail": "Reordering of rule permissions aborted as the list has changed while you were making changes. Please try again.",
"message.security.group.usage": "(Use <strong>Ctrl-clique</strong> para selecionar todos os Security Groups)",
"message.select.a.zone": "A zone tipicamente corresponde a um ?nico datacenter. M?ltiplas zonas auxiliam a cloud a ser mais confi?vel provendo isolamento f?sico e redund?ncia.",
diff --git a/ui/l10n/ru_RU.js b/ui/l10n/ru_RU.js
index 2c5b1a63c09..aaa40b8f9a3 100644
--- a/ui/l10n/ru_RU.js
+++ b/ui/l10n/ru_RU.js
@@ -20,7 +20,7 @@ var dictionary = {
"changed.item.properties": "????????? ???????? ????????",
"confirm.enable.s3": "????????? ?????????? ??? ????????? S3-???????????? ??????????????? ?????????",
"confirm.enable.swift": "????????? ????????????? ?????????? ??? ????????? ???????? Swift",
- "error.could.not.change.your.password.because.ldap.is.enabled": "Error could not change your password because LDAP is enabled.",
+ "error.could.not.change.your.password.because.non.native.user": "Error could not change your password because LDAP is enabled.",
"error.could.not.enable.zone": "?? ??????? ???????? ????",
"error.installWizard.message": "???-?? ?? ???. ????????? ????? ? ????????? ??????.",
"error.invalid.username.password": "???????????? ????? ??? ??????",
@@ -2176,6 +2176,7 @@ var dictionary = {
"message.restart.vpc": "???????????, ??? ?? ????????????? ?????? ????????????? VPC",
"message.restart.vpc.remark": "Please confirm that you want to restart the VPC <p><small><i>Remark: making a non-redundant VPC redundant will force a clean up. The networks will not be available for a couple of minutes</i>.</small></p>",
"message.restoreVM": "Do you want to restore the VM ?",
+ "message.role.update.fail": "Failed updating rule permission",
"message.role.ordering.fail": "Reordering of rule permissions aborted as the list has changed while you were making changes. Please try again.",
"message.security.group.usage": "(??????????? <strong>Ctrl-click</strong> ??? ?????? ???? ?????????? security groups)",
"message.select.a.zone": "???? ?????? ????????????? ?????????? ?????? ????????? ??????. ????????? ??? ???????? ????????? ????? ???????? ??????, ??????????? ?????????? ???????? ? ????????????.",
diff --git a/ui/l10n/zh_CN.js b/ui/l10n/zh_CN.js
index 2ba1c1f3197..2131c985cff 100644
--- a/ui/l10n/zh_CN.js
+++ b/ui/l10n/zh_CN.js
@@ -20,7 +20,7 @@ var dictionary = {
"changed.item.properties": "??????",
"confirm.enable.s3": "??????????? S3 ??????????",
"confirm.enable.swift": "??????????? SWIFT ???",
- "error.could.not.change.your.password.because.ldap.is.enabled": "???LDAP ????????????????",
+ "error.could.not.change.your.password.because.non.native.user": "???LDAP ????????????????",
"error.could.not.enable.zone": "???????",
"error.installWizard.message": "???????????????",
"error.invalid.username.password": "????????",
@@ -2180,6 +2180,7 @@ var dictionary = {
"message.restart.vpc": "??????????? VPC",
"message.restart.vpc.remark": "???????VPC <p><small><i> ??: ??????VPC????????,??VPC????</i>.</small></p>",
"message.restoreVM": "?????? VM?",
+ "message.role.update.fail": "Failed updating rule permission",
"message.role.ordering.fail": "Reordering of rule permissions aborted as the list has changed while you were making changes. Please try again.",
"message.security.group.usage": "(<strong>?? Ctrl ??????</strong>???????????)",
"message.select.a.zone": "?????????????????????????????????????????????",
diff --git a/ui/plugins/cloudian/cloudian.css b/ui/plugins/cloudian/cloudian.css
new file mode 100644
index 00000000000..447cf434b32
--- /dev/null
+++ b/ui/plugins/cloudian/cloudian.css
@@ -0,0 +1,18 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
diff --git a/ui/plugins/cloudian/cloudian.js b/ui/plugins/cloudian/cloudian.js
new file mode 100644
index 00000000000..1b8a35ab1e9
--- /dev/null
+++ b/ui/plugins/cloudian/cloudian.js
@@ -0,0 +1,66 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+(function (cloudStack) {
+ cloudStack.plugins.cloudian = function(plugin) {
+
+ plugin.ui.addSection({
+ id: 'cloudian',
+ title: 'Cloudian Storage',
+ showOnNavigation: true,
+ preFilter: function(args) {
+ var pluginEnabled = false;
+ $.ajax({
+ url: createURL('cloudianIsEnabled'),
+ async: false,
+ success: function(json) {
+ var response = json.cloudianisenabledresponse.cloudianisenabled;
+ pluginEnabled = response.enabled;
+ if (pluginEnabled) {
+ var cloudianLogoutUrl = response.url + "logout.htm?";
+ onLogoutCallback = function() {
+ g_loginResponse = null;
+ var csUrl = window.location.href;
+ var redirect = "redirect=" + encodeURIComponent(csUrl);
+ window.location.replace(cloudianLogoutUrl + redirect);
+ return false;
+ };
+ }
+ }
+ });
+ return pluginEnabled;
+ },
+
+ show: function() {
+ var description = 'Cloudian Management Console should open in another window.';
+ $.ajax({
+ url: createURL('cloudianSsoLogin'),
+ async: false,
+ success: function(json) {
+ var response = json.cloudianssologinresponse.cloudianssologin;
+ var cmcWindow = window.open(response.url, "CMCWindow");
+ cmcWindow.focus();
+ },
+ error: function(data) {
+ description = 'Single-Sign-On failed for Cloudian Management Console. Please ask your administrator to fix integration issues.';
+ }
+ });
+ return $('<div style="margin: 20px;">').html(description);
+ }
+ });
+ };
+}(cloudStack));
diff --git a/ui/plugins/cloudian/config.js b/ui/plugins/cloudian/config.js
new file mode 100644
index 00000000000..b72cd5f2ff9
--- /dev/null
+++ b/ui/plugins/cloudian/config.js
@@ -0,0 +1,25 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+(function (cloudStack) {
+ cloudStack.plugins.cloudian.config = {
+ title: 'Cloudian Storage',
+ desc: 'Cloudian Storage',
+ externalLink: 'https://cloudian.com/',
+ authorName: 'Cloudian Inc.',
+ authorEmail: 'info@cloudian.com '
+ };
+}(cloudStack));
diff --git a/ui/plugins/cloudian/icon.png b/ui/plugins/cloudian/icon.png
new file mode 100644
index 00000000000..d18ec237678
Binary files /dev/null and b/ui/plugins/cloudian/icon.png differ
diff --git a/ui/plugins/plugins.js b/ui/plugins/plugins.js
index 21da7a07f4d..6edfe88fe1d 100644
--- a/ui/plugins/plugins.js
+++ b/ui/plugins/plugins.js
@@ -17,6 +17,7 @@
(function($, cloudStack) {
cloudStack.plugins = [
//'testPlugin',
+ 'cloudian',
'quota'
];
}(jQuery, cloudStack));
diff --git a/ui/scripts/accounts.js b/ui/scripts/accounts.js
index 4488fdcc9cd..77c528f2ed1 100644
--- a/ui/scripts/accounts.js
+++ b/ui/scripts/accounts.js
@@ -895,6 +895,199 @@
}
},
+ sslCertificates: {
+ title: 'label.sslcertificates',
+ listView: {
+ id: 'sslCertificates',
+
+ fields: {
+ name: {
+ label: 'label.name'
+ },
+ id: {
+ label: 'label.certificateid'
+ }
+ },
+
+ dataProvider: function(args) {
+ var data = {};
+ listViewDataProvider(args, data);
+ if (args.context != null) {
+ if ("accounts" in args.context) {
+ $.extend(data, {
+ accountid: args.context.accounts[0].id
+ });
+ }
+ }
+ $.ajax({
+ url: createURL('listSslCerts'),
+ data: data,
+ success: function(json) {
+ var items = json.listsslcertsresponse.sslcert;
+ args.response.success({
+ data: items
+ });
+ }
+ });
+ },
+
+ actions: {
+ add: {
+ label: 'label.add.certificate',
+
+ messages: {
+ notification: function(args) {
+ return 'label.add.certificate';
+ }
+ },
+
+ createForm: {
+ title: 'label.add.certificate',
+ fields: {
+ name: {
+ label: 'label.name',
+ validation: {
+ required: true
+ }
+ },
+ certificate: {
+ label: 'label.certificate.name',
+ isTextarea: true,
+ validation: {
+ required: true
+ },
+ },
+ privatekey: {
+ label: 'label.privatekey.name',
+ isTextarea: true,
+ validation: {
+ required: true
+ }
+ },
+ certchain: {
+ label: "label.chain",
+ isTextarea: true,
+ validation: {
+ required: false
+ }
+ },
+ password: {
+ label: "label.privatekey.password",
+ isPassword: true,
+ validation: {
+ required: false
+ }
+ }
+ }
+ },
+
+ action: function(args) {
+ var data = {
+ name: args.data.name,
+ certificate: args.data.certificate,
+ privatekey: args.data.privatekey
+ };
+
+ if (args.data.certchain != null && args.data.certchain.length > 0) {
+ $.extend(data, {
+ certchain: args.data.certchain
+ });
+ }
+
+ if (args.data.password != null && args.data.password.length > 0) {
+ $.extend(data, {
+ password: args.data.password
+ });
+ }
+
+ $.ajax({
+ url: createURL('uploadSslCert'),
+ data: data,
+ success: function(json) {
+ var item = json.uploadsslcertresponse.sslcert;
+ args.response.success({
+ data: item
+ });
+ },
+ error: function(json) {
+ args.response.error(parseXMLHttpResponse(json));
+ }
+ });
+ }
+ }
+ },
+
+ detailView: {
+ actions: {
+ remove: {
+ label: 'label.delete.sslcertificate',
+ messages: {
+ confirm: function(args) {
+ return 'message.delete.sslcertificate';
+ },
+ notification: function(args) {
+ return 'label.delete.sslcertificate';
+ }
+ },
+ action: function(args) {
+ $.ajax({
+ url: createURL('deleteSslCert'),
+ data: {
+ id: args.context.sslCertificates[0].id
+ },
+ success: function(json) {
+ var items = json.deletesslcertresponse.sslcert;
+ args.response.success({
+ data: items
+ });
+ }
+ });
+ }
+ }
+ },
+
+ tabs: {
+ details: {
+ title: 'label.certificate.details',
+ fields: {
+ name: {
+ label: 'label.name'
+ },
+ certificate: {
+ label: 'label.certificate.name'
+ },
+ certchain: {
+ label: 'label.chain'
+ }
+ },
+
+ dataProvider: function(args) {
+ var data = {};
+
+ if (args.context != null) {
+ if ("sslCertificates" in args.context) {
+ $.extend(data, {
+ certid: args.context.sslCertificates[0].id
+ });
+ }
+ }
+ $.ajax({
+ url: createURL('listSslCerts'),
+ data: data,
+ success: function(json) {
+ var items = json.listsslcertsresponse.sslcert[0];
+ args.response.success({
+ data: items
+ });
+ }
+ });
+ }
+ }
+ }
+ }
+ }
+ },
+
// Granular settings for account
settings: {
title: 'label.settings',
@@ -1267,9 +1460,8 @@
var complete = args.complete;
var context = args.context;
- if (isLdapEnabled()) {
- cloudStack.dialog.notice({ message: _l('error.could.not.change.your.password.because.ldap.is.enabled') });
- } else {
+ var userSource = context.users[0].usersource;
+ if (userSource == "native") {
cloudStack.dialog.createForm({
form: {
title: 'label.action.change.password',
@@ -1316,6 +1508,8 @@
});
}
});
+ } else {
+ cloudStack.dialog.notice({ message: _l('error.could.not.change.your.password.because.non.native.user') });
}
}
}
@@ -1754,7 +1948,11 @@
select: function(args) {
if (isAdmin() || isDomainAdmin()) {
$.ajax({
- url: createURL("listDomains&listAll=true"),
+ url: createURL('listDomains'),
+ data: {
+ listAll: true,
+ details: 'min'
+ },
success: function(json) {
var items = [];
items.push({
diff --git a/ui/scripts/configuration.js b/ui/scripts/configuration.js
index 512ccf7c738..6c3ffd81687 100644
--- a/ui/scripts/configuration.js
+++ b/ui/scripts/configuration.js
@@ -1287,7 +1287,11 @@
dependsOn: 'isPublic',
select: function(args) {
$.ajax({
- url: createURL("listDomains&listAll=true"),
+ url: createURL('listDomains'),
+ data: {
+ listAll: true,
+ details: 'min'
+ },
dataType: "json",
async: false,
success: function(json) {
@@ -1999,7 +2003,11 @@
dependsOn: 'isPublic',
select: function(args) {
$.ajax({
- url: createURL("listDomains&listAll=true"),
+ url: createURL('listDomains'),
+ data: {
+ listAll: true,
+ details: 'min'
+ },
dataType: "json",
async: false,
success: function(json) {
@@ -2639,11 +2647,17 @@
args.$form.find('.form-item[rel=\"egressdefaultpolicy\"]').css('display', 'none');
}
- //show LB Isolation dropdown only when (1)LB Service is checked (2)Service Provider is Netscaler OR F5
- if ((args.$form.find('.form-item[rel=\"service.Lb.isEnabled\"]').find('input[type=checkbox]').is(':checked') == true) && (args.$form.find('.form-item[rel=\"service.Lb.provider\"]').find('select').val() == 'Netscaler' || args.$form.find('.form-item[rel=\"service.Lb.provider\"]').find('select').val() == 'F5BigIp')) {
- args.$form.find('.form-item[rel=\"service.Lb.lbIsolationDropdown\"]').css('display', 'inline-block');
+ //show Netscaler service packages only when (1)LB Service is checked (2)Service Provider is Netscaler
+ if ((args.$form.find('.form-item[rel=\"service.Lb.isEnabled\"]').find('input[type=checkbox]').is(':checked') == true) && (args.$form.find('.form-item[rel=\"service.Lb.provider\"]').find('select').val() == 'Netscaler')) {
+ args.$form.find('.form-item[rel=\"service.Lb.Netscaler.servicePackages\"]').css('display', 'inline-block');
+ args.$form.find('.form-item[rel=\"service.Lb.Netscaler.servicePackages.description\"]').css('display', 'inline-block');
+ args.$form.find('.form-item[rel=\"service.Lb.Netscaler.servicePackages.description\"]').find("#label_netscaler_service_packages_description").attr("disabled", "disabled");
+ args.$form.find('.form-item[rel=\"service.Lb.Netscaler.servicePackages.description\"]').find("#label_netscaler_service_packages_description").text(args.$form.find('.form-item[rel=\"service.Lb.Netscaler.servicePackages\"]').find('#label_netscaler_service_packages option:selected').data("json-obj").desc);
} else {
- args.$form.find('.form-item[rel=\"service.Lb.lbIsolationDropdown\"]').hide();
+ args.$form.find('.form-item[rel=\"service.Lb.Netscaler.servicePackages\"]').hide();
+ args.$form.find('.form-item[rel=\"service.Lb.Netscaler.servicePackages.description\"]').hide();
+ args.$form.find('.form-item[rel=\"service.Lb.Netscaler.servicePackages.description\"]').find("#label_netscaler_service_packages_description").attr("disabled", "disabled");
+ args.$form.find('.form-item[rel=\"service.Lb.Netscaler.servicePackages.description\"]').find("#label_netscaler_service_packages_description").text("");
}
//show Elastic LB checkbox only when (1)LB Service is checked (2)Service Provider is Netscaler (3)Guest IP Type is Shared
@@ -2797,6 +2811,60 @@
}
},
+ promiscuousMode: {
+ label: 'label.promiscuous.mode',
+ select: function(args) {
+ args.response.success({
+ data: [{
+ id: '',
+ description: ''
+ }, {
+ id: 'true',
+ description: 'Accept'
+ }, {
+ id: 'false',
+ description: 'Reject'
+ }]
+ });
+ }
+ },
+
+ macAddressChanges: {
+ label: 'label.mac.address.changes',
+ select: function(args) {
+ args.response.success({
+ data: [{
+ id: '',
+ description: ''
+ }, {
+ id: 'true',
+ description: 'Accept'
+ }, {
+ id: 'false',
+ description: 'Reject'
+ }]
+ });
+ }
+ },
+
+ forgedTransmits: {
+ label: 'label.forged.transmits',
+ select: function(args) {
+ args.response.success({
+ data: [{
+ id: '',
+ description: ''
+ }, {
+ id: 'true',
+ description: 'Accept'
+ }, {
+ id: 'false',
+ description: 'Reject'
+ }]
+ });
+ }
+ },
+
supportedServices: {
label: 'label.supported.services',
@@ -3014,22 +3082,7 @@
isHidden: true,
isBoolean: true
},
- "service.Lb.lbIsolationDropdown": {
- label: 'label.LB.isolation',
- docID: 'helpNetworkOfferingLBIsolation',
- isHidden: true,
- select: function(args) {
- args.response.success({
- data: [{
- id: 'dedicated',
- description: 'Dedicated'
- }, {
- id: 'shared',
- description: 'Shared'
- }]
- })
- }
- },
+
"service.Lb.inlineModeDropdown": {
label: 'label.mode',
docID: 'helpNetworkOfferingMode',
@@ -3049,6 +3102,62 @@
}
},
+ "service.Lb.Netscaler.servicePackages": {
+ label: 'label.netscaler.service.packages',
+ docID: 'helpNetscalerServicePackages',
+ isHidden: true,
+ select: function(args) {
+ $.ajax({
+ url: createURL('listRegisteredServicePackages'),
+ dataType: 'json',
+ async: true,
+ success: function(data) {
+ var servicePackages = data.listregisteredservicepackage.registeredServicepackage;
+
+ if (servicePackages == undefined || servicePackages == null || !servicePackages) {
+ servicePackages = data.listregisteredservicepackage;
+ }
+
+ args.response.success({
+ data: $.map(servicePackages, function(elem) {
+ return {
+ id: elem.id,
+ description: elem.name,
+ desc: elem.description
+ };
+ })
+ });
+ },
+ error: function(data) {
+ args.response.error(parseXMLHttpResponse(data));
+ }
+ });
+ }
+ },
+
+ "service.Lb.Netscaler.servicePackages.description": {
+ label: 'label.netscaler.service.packages.description',
+ isHidden: true,
+ isTextarea: true
+ },
+
+ "service.Lb.lbIsolationDropdown": {
+ label: 'label.LB.isolation',
+ docID: 'helpNetworkOfferingLBIsolation',
+ isHidden: true,
+ select: function(args) {
+ args.response.success({
+ data: [{
+ id: 'dedicated',
+ description: 'Dedicated'
+ }, {
+ id: 'shared',
+ description: 'Shared'
+ }]
+ })
+ }
+ },
+
"service.StaticNat.elasticIpCheckbox": {
label: "label.elastic.IP",
isHidden: true,
@@ -3129,6 +3238,12 @@
$.each(formData, function(key, value) {
var serviceData = key.split('.');
+ if (key == 'service.Lb.Netscaler.servicePackages' && value != "") {
+ inputData['details[' + 0 + '].servicepackageuuid'] = value;
+ inputData['details[' + 1 + '].servicepackagedescription'] = args.$form.find('#label_netscaler_service_packages option:selected').data().jsonObj.desc;
+ }
+
+
if (serviceData.length > 1) {
if (serviceData[0] == 'service' &&
serviceData[2] == 'isEnabled' &&
@@ -3280,6 +3395,22 @@
delete inputData.egressdefaultpolicy;
}
+ if ("promiscuousMode" in inputData) {
+ inputData['details[0].promiscuousMode'] = inputData.promiscuousMode;
+ delete inputData.promiscuousMode;
+ }
+
+ if ("macAddressChanges" in inputData) {
+ inputData['details[0].macAddressChanges'] = inputData.macAddressChanges;
+ delete inputData.macAddressChanges;
+ }
+
+ if ("forgedTransmits" in inputData) {
+ inputData['details[0].forgedTransmits'] = inputData.forgedTransmits;
+ delete inputData.forgedTransmits;
+ }
+
+
if (args.$form.find('.form-item[rel=serviceofferingid]').css("display") == "none")
delete inputData.serviceofferingid;
@@ -3578,6 +3709,9 @@
},
tags: {
label: 'label.tags'
+ },
+ details: {
+ label: 'label.details'
}
}],
@@ -3588,9 +3722,16 @@
async: true,
success: function(json) {
var item = json.listnetworkofferingsresponse.networkoffering[0];
+ if (!item.hasOwnProperty('details')) {
+ item.details = {};
+ }
args.response.success({
actionFilter: networkOfferingActionfilter,
data: $.extend(item, {
+ details: $.map(item.details, function(val, key) {
+ return key + "=" + val;
+ }).join(', '),
+
supportedServices: $.map(item.service, function(service) {
return service.name;
}).join(', '),
diff --git a/ui/scripts/dashboard.js b/ui/scripts/dashboard.js
index bd328634bb7..a30e1cd9c2d 100644
--- a/ui/scripts/dashboard.js
+++ b/ui/scripts/dashboard.js
@@ -246,8 +246,6 @@
data: {
fetchLatest: data.fetchLatest,
sortBy: 'usage',
- page: 0,
- pageSize: (pageSize > 8? 8: pageSize)
},
success: function(json) {
var capacities = json.listcapacityresponse.capacity ?
@@ -269,7 +267,7 @@
zoneID: capacity.zoneid, // Temporary fix for dashboard
zoneName: capacity.zonename,
type: cloudStack.converters.toCapacityCountType(capacity.type),
- percent: parseInt(capacity.percentused),
+ percent: capacity.percentused,
used: cloudStack.converters.convertByType(capacity.type, capacity.capacityused),
total: cloudStack.converters.convertByType(capacity.type, capacity.capacitytotal)
};
diff --git a/ui/scripts/docs.js b/ui/scripts/docs.js
index 938514f84d2..2908e8b5f64 100755
--- a/ui/scripts/docs.js
+++ b/ui/scripts/docs.js
@@ -568,6 +568,10 @@ cloudStack.docs = {
desc: 'Number of guest networks/accounts that will share this device',
externalLink: ''
},
+ helpNetscalerServicePackages: {
+ desc: 'Choose the Netscaler Service Package you want to use.',
+ externalLink: ''
+ },
// Add network offering
helpNetworkOfferingName: {
desc: 'Any desired name for the network offering',
diff --git a/ui/scripts/domains.js b/ui/scripts/domains.js
index 9dc801bfc0a..04f523c2378 100644
--- a/ui/scripts/domains.js
+++ b/ui/scripts/domains.js
@@ -771,7 +771,9 @@
} else if (isDomainAdmin()) {
if (args.context.domains[0].id != g_domainid) {
allowedActions.push("edit"); //merge updateResourceLimit into edit
+ allowedActions.push("delete");
}
+ allowedActions.push("create");
}
allowedActions.push("updateResourceCount");
return allowedActions;
diff --git a/ui/scripts/instances.js b/ui/scripts/instances.js
index 67f4709b609..252eb1ac84b 100644
--- a/ui/scripts/instances.js
+++ b/ui/scripts/instances.js
@@ -1540,6 +1540,7 @@
id: this.id,
availableHostName: this.name,
availableHostSuitability: suitability,
+ requiresStorageMotion: this.requiresStorageMotion,
cpuused: this.cpuused,
memoryused: (parseFloat(this.memoryused)/(1024.0*1024.0*1024.0)).toFixed(2) + ' GB'
});
diff --git a/ui/scripts/lbCertificatePolicy.js b/ui/scripts/lbCertificatePolicy.js
new file mode 100644
index 00000000000..538e33dcc03
--- /dev/null
+++ b/ui/scripts/lbCertificatePolicy.js
@@ -0,0 +1,183 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+(function($, cloudStack) {
+ cloudStack.lbCertificatePolicy = {
+ dialog: function(args) {
+ return function(args) {
+ var success = args.response.success;
+ var context = args.context;
+
+ var certid = {
+ certificate: {
+ label: 'label.certificate.name',
+ select: function(args) {
+ var data = {};
+ var item = {};
+
+ if (context != null) {
+ if (context.networks != null) {
+ $.extend(data, {account: context.networks[0].account});
+ $.extend(data, {domain: context.networks[0].domain});
+ }
+ }
+
+ $.ajax({
+ url: createURL('listAccounts'),
+ async: false,
+ data: data,
+ success: function(json) {
+ var items = json.listaccountsresponse.account;
+ $.extend(item, {accountid: items[0].id});
+ }
+ });
+
+ $.ajax({
+ url: createURL('listSslCerts'),
+ async: false,
+ data: item,
+ success: function(json) {
+ var items = json.listsslcertsresponse.sslcert;
+ args.response.success({
+ data: $.map(items, function(item) {
+ return {
+ id: item.id,
+ description: item.id
+ };
+ })
+ });
+ }
+ });
+ }
+ }
+ };
+
+ var $item = args.$item;
+
+ cloudStack.dialog.createForm({
+ form: {
+ title: 'Configure Certificate',
+ desc: 'Please complete the following fields',
+ fields: certid
+ },
+ after: function(args) {
+ // Remove fields not applicable to sticky method
+ args.$form.find('.form-item:hidden').remove();
+
+ var data = cloudStack.serializeForm(args.$form);
+
+ /* $item indicates that this is an existing sticky rule;
+ re-create sticky rule with new parameters */
+ if ($item) {
+ var $loading = $('<div>').addClass('loading-overlay');
+
+ $loading.prependTo($item);
+ cloudStack.lbStickyPolicy.actions.recreate(
+ $item.data('multi-custom-data').id,
+ $item.data('multi-custom-data').lbRuleID,
+ data,
+ function() { // Complete
+ $(window).trigger('cloudStack.fullRefresh');
+ },
+ function(error) { // Error
+ $(window).trigger('cloudStack.fullRefresh');
+ }
+ );
+ } else {
+ success({
+ data: data
+ });
+ }
+ }
+ });
+ };
+ },
+
+ actions: {
+ add: function(lbRuleID, data, complete, error) {
+
+ $.ajax({
+ url: createURL('assignCertToLoadBalancer'),
+ data: {certid: data.certificate, lbruleid: lbRuleID},
+ success: function(json) {
+ cloudStack.ui.notifications.add({
+ desc: 'Add new LB Certificate',
+ section: 'Network',
+ poll: pollAsyncJobResult,
+ _custom: {
+ jobId: json.assigncerttoloadbalancerresponse.jobid
+ }
+ },
+ complete, {},
+ error, {}
+ );
+ },
+ error: function(json) {
+ complete();
+ cloudStack.dialog.notice({
+ message: parseXMLHttpResponse(json)
+ });
+ }
+ });
+ },
+ 'delete': function(stickyRuleID, complete, error) {
+ $.ajax({
+ url: createURL('deleteLBStickinessPolicy'),
+ data: {
+ id: stickyRuleID
+ },
+ success: function(json) {
+ cloudStack.ui.notifications.add({
+ desc: 'Remove previous LB sticky rule',
+ section: 'Network',
+ poll: pollAsyncJobResult,
+ _custom: {
+ jobId: json.deleteLBstickinessrruleresponse.jobid
+ }
+ },
+ complete, {},
+ error, {}
+ );
+ },
+ error: function(json) {
+ complete();
+ cloudStack.dialog.notice({
+ message: parseXMLHttpResponse(json)
+ });
+ }
+ });
+ },
+ recreate: function(stickyRuleID, lbRuleID, data, complete, error) {
+ var addStickyPolicy = function() {
+ cloudStack.lbStickyPolicy.actions.add(
+ lbRuleID,
+ data,
+ complete,
+ error
+ );
+ };
+
+ // Delete existing rule
+ if (data.methodname !== 'None') {
+ addStickyPolicy();
+ } else {
+ cloudStack.lbStickyPolicy.actions['delete'](stickyRuleID, complete, error);
+ }
+ }
+ }
+ };
+}(jQuery, cloudStack));
\ No newline at end of file
diff --git a/ui/scripts/network.js b/ui/scripts/network.js
old mode 100755
new mode 100644
index 72aa3ad1103..83701065c60
--- a/ui/scripts/network.js
+++ b/ui/scripts/network.js
@@ -408,6 +408,23 @@
}
}
}
+ //Ajax call to check if VPN is enabled.
+ $.ajax({
+ url: createURL('listRemoteAccessVpns'),
+ data: {
+ account: g_account,
+ domainid: g_domainid,
+ listAll: true
+ },
+ async: false,
+ success: function(vpnResponse) {
+ var isVPNEnabled = vpnResponse.listremoteaccessvpnsresponse.count;
+
+ if (isVPNEnabled) {
+ sectionsToShow.push('vpnuser');
+ }
+ }
+ });
}
});
@@ -974,14 +991,14 @@
cloudStack.dialog.confirm({
message: 'message.confirm.current.guest.CIDR.unchanged',
action: function() { //"Yes" button is clicked
- getForcedInfoAndUpdateNetwork(data);
+ getForcedInfoAndUpdateNetwork(data, args);
},
cancelAction: function() { //"Cancel" button is clicked
$.extend(data, {
changecidr: true
});
- getForcedInfoAndUpdateNetwork(data);
+ getForcedInfoAndUpdateNetwork(data, args);
}
});
return;
@@ -3033,112 +3050,6 @@
vmDetails: cloudStack.sections.instances.listView.detailView,
-
- //"NAT Port Range" multiEdit screen for StaticNAT is obsolete in cloudstack 3.0 because createIpForwardingRule/deleteIpForwardingRule/listIpForwardingRules API are obsolete in cloudstack 3.0.
- //cloudstack 3.0 is using createFirewallRule/listFirewallRules/deleteFirewallRule API for both staticNAT and non-staticNAT .
- /*
- staticNAT: {
- noSelect: true,
- fields: {
- 'protocol': {
- label: 'label.protocol',
- select: function(args) {
- args.response.success({
- data: [
- { name: 'tcp', description: 'TCP' },
- { name: 'udp', description: 'UDP' }
- ]
- });
- }
- },
- 'startport': { edit: true, label: 'label.start.port' },
- 'endport': { edit: true, label: 'label.end.port' },
- 'add-rule': {
- label: 'label.add.rule',
- addButton: true
- }
- },
- add: {
- label: 'label.add',
- action: function(args) {
- $.ajax({
- url: createURL('createIpForwardingRule'),
- data: $.extend(args.data, {
- ipaddressid: args.context.ipAddresses[0].id
- }),
- dataType: 'json',
- success: function(data) {
- args.response.success({
- _custom: {
- jobId: data.createipforwardingruleresponse.jobid
- },
- notification: {
- label: 'label.add.static.nat.rule',
- poll: pollAsyncJobResult
- }
- });
- },
- error: function(data) {
- args.response.error(parseXMLHttpResponse(data));
- }
- });
- }
- },
- actions: {
- destroy: {
- label: 'label.remove.rule',
- action: function(args) {
- $.ajax({
- url: createURL('deleteIpForwardingRule'),
- data: {
- id: args.context.multiRule[0].id
- },
- dataType: 'json',
- async: true,
- success: function(data) {
- var jobID = data.deleteipforwardingruleresponse.jobid;
- args.response.success({
- _custom: {
- jobId: jobID
- },
- notification: {
- label: 'label.remove.static.nat.rule',
- poll: pollAsyncJobResult
- }
- });
- },
- error: function(data) {
- args.response.error(parseXMLHttpResponse(data));
- }
- });
- }
- }
- },
- dataProvider: function(args) {
- setTimeout(function() {
- $.ajax({
- url: createURL('listIpForwardingRules'),
- data: {
- listAll: true,
- ipaddressid: args.context.ipAddresses[0].id
- },
- dataType: 'json',
- async: true,
- success: function(data) {
- args.response.success({
- data: data.listipforwardingrulesresponse.ipforwardingrule
- });
- },
- error: function(data) {
- args.response.error(parseXMLHttpResponse(data));
- }
- });
- }, 100);
- }
- },
- */
-
-
// Load balancing rules
loadBalancing: {
listView: $.extend(true, {}, cloudStack.sections.instances, {
@@ -3368,6 +3279,41 @@
}
},
+ 'protocol': {
+ label: 'label.protocol',
+ isEditable: true,
+ select: function(args) {
+ var data = [{
+ id: 'ssl',
+ name: 'ssl',
+ description: _l('label.lb.protocol.ssl')
+ }, {
+ id: 'tcp',
+ name: 'tcp',
+ description: _l('label.lb.protocol.tcp')
+ }, {
+ id: 'udp',
+ name: 'udp',
+ description: _l('label.lb.protocol.udp')
+ }];
+ if (typeof args.context != 'undefined') {
+ var lbProtocols = getLBProtocols(args.context.networks[0]);
+ data = (lbProtocols.length == 0) ? data : lbProtocols;
+ }
+ args.response.success({
+ data: data
+ });
+ }
+ },
+
+ 'sslcertificate': {
+ label: 'label.update.ssl',
+ custom: {
+ buttonLabel: 'label.configure',
+ action: cloudStack.lbCertificatePolicy.dialog()
+ }
+ },
+
'health-check': {
label: 'label.health.check',
custom: {
@@ -3449,12 +3395,10 @@
}
}
},
-
'add-vm': {
label: 'label.add.vms',
addButton: true
},
-
'state' : {
edit: 'ignore',
label: 'label.state'
@@ -3486,11 +3430,13 @@
publicport: args.data.publicport,
openfirewall: false,
networkid: networkid,
- publicipid: args.context.ipAddresses[0].id
+ publicipid: args.context.ipAddresses[0].id,
+ protocol: args.data.protocol
};
var stickyData = $.extend(true, {}, args.data.sticky);
-
+ var certificateData = $.extend(true, {}, args.data.sslcertificate);
+
//***** create new LB rule > Add VMs *****
$.ajax({
url: createURL('createLoadBalancerRule'),
@@ -3503,46 +3449,70 @@
var lbID = data.createloadbalancerruleresponse.id;
var inputData = {
- id: data.createloadbalancerruleresponse.id
- };
-
- /*
- var inputData = {
- id: data.createloadbalancerruleresponse.id,
- virtualmachineids: $.map(itemData, function(elem) {
- return elem.id;
- }).join(',')
- };
- */
- //virtualmachineids parameter has been replaced with vmidipmap parameter, so comment out the 6 lines above.
-
-
- /*
- * e.g. first VM(xxx) has two IPs(10.1.1.~), second VM(yyy) has three IPs(10.2.2.~):
- * vmidipmap[0].vmid=xxx vmidipmap[0].vmip=10.1.1.11
- * vmidipmap[1].vmid=xxx vmidipmap[1].vmip=10.1.1.12
- * vmidipmap[2].vmid=yyy vmidipmap[2].vmip=10.2.2.77
- * vmidipmap[3].vmid=yyy vmidipmap[3].vmip=10.2.2.78
- * vmidipmap[4].vmid=yyy vmidipmap[4].vmip=10.2.2.79
- */
+ id: data.createloadbalancerruleresponse.id
+ };
+
var selectedVMs = args.itemData;
if (selectedVMs != null) {
- var vmidipmapIndex = 0;
- for (var vmIndex = 0; vmIndex < selectedVMs.length; vmIndex++) {
- var selectedIPs = selectedVMs[vmIndex]._subselect;
- for (var ipIndex = 0; ipIndex < selectedIPs.length; ipIndex++) {
- inputData['vmidipmap[' + vmidipmapIndex + '].vmid'] = selectedVMs[vmIndex].id;
-
- if (args.context.ipAddresses[0].isportable) {
- inputData['vmidipmap[' + vmidipmapIndex + '].vmip'] = selectedIPs[ipIndex].split(',')[1];
- } else {
- inputData['vmidipmap[' + vmidipmapIndex + '].vmip'] = selectedIPs[ipIndex];
- }
+ var vmidipmapIndex = 0;
+ for (var vmIndex = 0; vmIndex < selectedVMs.length; vmIndex++) {
+ var selectedIPs = selectedVMs[vmIndex]._subselect;
+ for (var ipIndex = 0; ipIndex < selectedIPs.length; ipIndex++) {
+ inputData['vmidipmap[' + vmidipmapIndex + '].vmid'] = selectedVMs[vmIndex].id;
+
+ if (args.context.ipAddresses[0].isportable) {
+ inputData['vmidipmap[' + vmidipmapIndex + '].vmip'] = selectedIPs[ipIndex].split(',')[1];
+ } else {
+ inputData['vmidipmap[' + vmidipmapIndex + '].vmip'] = selectedIPs[ipIndex];
+ }
+
+ vmidipmapIndex++;
+ }
+ }
+ }
+
+ /*$.ajax({
+ url: createURL('assignCertToLoadBalancer'),
+ data: {certid: certificateData.certificate, lbruleid: lbID},
+ success: function(data) {
+ var jobID = data.assigncerttoloadbalancerresponse.jobid;
+ var lbProtocolCreated = false;
- vmidipmapIndex++;
- }
+ args.response.success({
+ _custom: {
+ jobId: jobID
+ },
+ notification: {
+ label: 'label.add.certificate',
+ poll: function(args) {
+ var complete = args.complete;
+ var error = args.error;
+
+ pollAsyncJobResult({
+ _custom: {
+ jobId: jobID
+ },
+ complete: function(args) {
+ if (lbProtocolCreated) return;
+
+ lbProtocolCreated = true;
+
+ if (certificateData && certificateData.certificate) {
+ cloudStack.lbCertificatePolicy.actions.add(lbID, certificateData, complete, error);
+ } else {
+ complete();
+ }
+ },
+ error: error
+ });
+ }
+ }
+ });
+ },
+ error: function(data) {
+ args.response.error(parseXMLHttpResponse(data));
}
- }
+ });*/
$.ajax({
url: createURL('assignToLoadBalancerRule'),
@@ -3550,6 +3520,7 @@
success: function(data) {
var jobID = data.assigntoloadbalancerruleresponse.jobid;
var lbStickyCreated = false;
+ var lbCertificateCreated = false;
args.response.success({
_custom: {
@@ -3566,17 +3537,26 @@
jobId: jobID
},
complete: function(args) {
- if (lbStickyCreated) return;
+ if (lbStickyCreated && lbCertificateCreated) {
+ return;
+ }
- lbStickyCreated = true;
+ if (!lbStickyCreated) {
+ lbStickyCreated = true;
- // Create stickiness policy
- if (stickyData &&
- stickyData.methodname &&
- stickyData.methodname != 'None') {
- cloudStack.lbStickyPolicy.actions.add(lbID,
- stickyData,
- complete, error);
+ if (stickyData && stickyData.methodname && stickyData.methodname != 'None') {
+ cloudStack.lbStickyPolicy.actions.add(lbID, stickyData, complete, error);
+ }
+ }
+
+ if (!lbCertificateCreated) {
+ lbCertificateCreated = true;
+
+ if (certificateData && certificateData.certificate && certificateData.certificate != 'None') {
+ cloudStack.lbCertificatePolicy.actions.add(lbID, certificateData, complete, error);
+ } else {
+ complete();
+ }
} else {
complete();
}
@@ -3769,7 +3749,7 @@
$(loadbalancerrules).each(function() {
var lbRule = this;
var stickyData = {};
-
+ var sslCertData = {};
//var lbInstances = [];
var itemData = [];
@@ -3830,6 +3810,21 @@
}
});
+ // Get SSL Certificate data
+ $.ajax({
+ url: createURL('listSslCerts'),
+ data: {
+ listAll: true,
+ lbruleid: lbRule.id
+ },
+ async: false,
+ success: function(json) {
+ if (json.listsslcertsresponse != null) {
+ lbRule._hideFields.push('sslcertificate');
+ }
+ }
+ });
+
// Get instances
$.ajax({
url: createURL('listLoadBalancerRuleInstances'),
@@ -4289,99 +4284,11 @@
$('<li>').addClass('psk').html(_l('message.enabled.vpn.ip.sec') + ' ')
.append($('<strong>').html(psk))
)
- ).multiEdit({
- context: args.context,
- noSelect: true,
- fields: {
- 'username': {
- edit: true,
- label: 'label.username'
- },
- 'password': {
- edit: true,
- isPassword: true,
- label: 'label.password'
- },
- 'add-user': {
- addButton: true,
- label: 'label.add.user'
- }
- },
- add: {
- label: 'label.add.user',
- action: function(args) {
- $.ajax({
- url: createURL('addVpnUser'),
- data: $.extend(args.data, {
- domainid: args.context.ipAddresses[0].domainid,
- account: args.context.ipAddresses[0].account
- }),
- dataType: 'json',
- type: "POST",
- success: function(data) {
- args.response.success({
- _custom: {
- jobId: data.addvpnuserresponse.jobid
- },
- notification: {
- label: 'label.add.vpn.user',
- poll: pollAsyncJobResult
- }
- });
- },
- error: function(data) {
- args.response.error(parseXMLHttpResponse(data));
- }
- });
- }
- },
- actions: {
- destroy: {
- label: 'label.action.delete.user',
- action: function(args) {
- $.ajax({
- url: createURL('removeVpnUser'),
- data: {
- domainid: args.context.multiRule[0].domainid,
- account: args.context.multiRule[0].account,
- username: args.context.multiRule[0].username
- },
- dataType: 'json',
- async: true,
- success: function(data) {
- var jobID = data.removevpnuserresponse.jobid;
-
- args.response.success({
- _custom: {
- jobId: jobID
- },
- notification: {
- label: 'label.delete.vpn.user',
- poll: pollAsyncJobResult
- }
- });
- }
- });
- }
- }
- },
- dataProvider: function(args) {
- $.ajax({
- url: createURL('listVpnUsers'),
- data: {
- domainid: args.context.ipAddresses[0].domainid,
- account: args.context.ipAddresses[0].account
- },
- dataType: 'json',
- async: true,
- success: function(data) {
- args.response.success({
- data: data.listvpnusersresponse.vpnuser
- });
- }
- });
- }
- });
+ .append(
+ //Note
+ $('<li>').html(_l('message.enabled.vpn.note'))
+ )
+ )
}
}
}
@@ -6369,6 +6276,284 @@
item.perfectForwardSecrecy = a2[1];
}
+ args.response.success({
+ data: item
+ });
+ }
+ });
+ }
+ }
+ }
+ }
+ }
+ },
+ vpnuser: {
+ type: 'select',
+ title: 'label.vpn.users',
+ listView: {
+ id: 'vpnUsers',
+ label: 'label.vpn.users',
+ fields: {
+ username: {
+ label: 'label.name'
+ },
+ domain: {
+ label: 'label.domain'
+ },
+ state: {
+ label: 'label.state'
+ }
+ },
+
+ dataProvider: function(args) {
+ var data = {};
+ listViewDataProvider(args, data);
+
+ $.ajax({
+ url: createURL('listVpnUsers'),
+ data: data,
+ dataType: 'json',
+ success: function(json) {
+ var items = json.listvpnusersresponse.vpnuser;
+ args.response.success({
+ data: items
+ });
+ }
+ });
+ },
+
+ actions:{
+ destroy: {
+ label: 'label.action.delete.user',
+ messages: {
+ confirm: function(args) {
+ return 'message.action.delete.vpn.user'
+ },
+ notification: function(args) {
+ return 'label.delete.vpn.user'
+ }
+ },
+ action: function(args) {
+ console.log(args.context);
+ $.ajax({
+ url: createURL('removeVpnUser'),
+ data: {
+ domainid: args.context.vpnuser[0].domainid,
+ account: args.context.vpnuser[0].account,
+ username: args.context.vpnuser[0].username
+ },
+ dataType: 'json',
+ async: true,
+ success: function(json) {
+ var jobID = json.removevpnuserresponse.jobid;
+ args.response.success({
+ _custom: {
+ jobId: jobID
+ }
+ });
+ }
+ });
+ },
+ notification: {
+ poll: pollAsyncJobResult
+ }
+ },
+ add: {
+ label: 'label.add.user',
+ messages: {
+ notification: function(args) {
+ return 'label.add.vpn.user';
+ }
+ },
+ createForm:{
+ title: 'label.add.vpn.user',
+ fields: {
+ username: {
+ edit: true,
+ label: 'label.username',
+ validation: {
+ required: true
+ }
+ },
+ password: {
+ edit: true,
+ isPassword: true,
+ label: 'label.password',
+ validation: {
+ required: true
+ }
+ },
+ domain: {
+ label: 'label.domain',
+ isHidden: function(args) {
+ if (isAdmin() || isDomainAdmin())
+ return false;
+ else
+ return true;
+ },
+ select: function(args) {
+ if (isAdmin() || isDomainAdmin()) {
+ $.ajax({
+ url: createURL("listDomains&listAll=true"),
+ success: function(json) {
+ var items = [];
+ items.push({
+ id: "",
+ description: ""
+ });
+ var domainObjs = json.listdomainsresponse.domain;
+ $(domainObjs).each(function() {
+ items.push({
+ id: this.id,
+ description: this.path
+ });
+ });
+ items.sort(function(a, b) {
+ return a.description.localeCompare(b.description);
+ });
+ args.response.success({
+ data: items
+ });
+ }
+ });
+ args.$select.change(function() {
+ var $form = $(this).closest('form');
+ if ($(this).val() == "") {
+ $form.find('.form-item[rel=account]').hide();
+ } else {
+ $form.find('.form-item[rel=account]').css('display', 'inline-block');
+ }
+ });
+ } else {
+ args.response.success({
+ data: null
+ });
+ }
+ }
+ },
+ account: {
+ label: 'label.account',
+ validation: {
+ required: true
+ },
+ isHidden: function(args) {
+ if (isAdmin() || isDomainAdmin()) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+ }
+ }
+ },
+ action: function(args) {
+ var data = {
+ username: args.data.username,
+ password: args.data.password
+ };
+
+ if (args.data.domain != null && args.data.domain.length > 0) {
+ $.extend(data, {
+ domainid: args.data.domain
+ });
+ if (args.data.account != null && args.data.account.length > 0) {
+ $.extend(data, {
+ account: args.data.account
+ });
+ }
+ }
+
+ $.ajax({
+ url: createURL('addVpnUser'),
+ data: data,
+ dataType: 'json',
+ async: true,
+ success: function(json) {
+ var jid = json.addvpnuserresponse.jobid;
+ args.response.success({
+ _custom: {
+ jobId: jid,
+ getUpdatedItem: function(json) {
+ return json.queryasyncjobresultresponse.jobresult.vpnuser;
+ }
+ }
+ });
+ }
+ });
+ },
+ notification: {
+ poll: pollAsyncJobResult
+ }
+ }
+ },
+
+ detailView: {
+ name: 'label.details',
+ actions: {
+ destroy: {
+ label: 'label.action.delete.user',
+ messages: {
+ confirm: function(args) {
+ return 'message.action.delete.vpn.user';
+ },
+ notification: function(args) {
+ return 'label.delete.vpn.user';
+ }
+ },
+ action: function(args) {
+ $.ajax({
+ url: createURL("removeVpnUser"),
+ data: {
+ domainid: args.context.vpnuser[0].domainid,
+ account: args.context.vpnuser[0].account,
+ username: args.context.vpnuser[0].username
+ },
+ dataType: 'json',
+ async: true,
+ success: function(json) {
+ var jid = json.removevpnuserresponse.jobid;
+ args.response.success({
+ _custom: {
+ jobId: jid
+ }
+ });
+ }
+ });
+ },
+ notification: {
+ poll: pollAsyncJobResult
+ }
+ }
+ },
+
+ tabs: {
+ details: {
+ title: 'label.details',
+ fields: [{
+ username: {
+ label: 'label.name',
+ validation: {
+ required: true
+ }
+ }
+ }, {
+ domain: {
+ label: 'label.domain'
+ },
+ state: {
+ label: 'label.state'
+ },
+ }],
+
+ dataProvider: function(args) {
+ $.ajax({
+ url: createURL("listVpnUsers"),
+ data: {
+ id: args.context.vpnuser[0].id
+ },
+ success: function(json) {
+ var item = json.listvpnusersresponse.vpnuser[0];
+
args.response.success({
data: item
});
@@ -6495,7 +6680,7 @@
return data;
}
- function getForcedInfoAndUpdateNetwork(data) {
+ function getForcedInfoAndUpdateNetwork(data, args) {
if (isAdmin()) {
cloudStack.dialog.confirm({
message: "message.confirm.force.update",
@@ -6570,4 +6755,63 @@
}
}
+ var getLBProtocols = function(networkObj) {
+ if (!networkObj || !networkObj.service) {
+ return [];
+ }
+
+ var lbService = $.grep(networkObj.service, function(service) {
+ return service.name == 'Lb';
+ })[0];
+
+ if (!lbService || !lbService.capability) {
+ return [];
+ }
+
+ var protocolCapabilities = $.grep(
+ lbService.capability,
+ function(capability) {
+ return (capability.name == 'SupportedProtocols');
+ }
+ )[0];
+
+ if (!protocolCapabilities) {
+ return [];
+ }
+
+ var protocols = protocolCapabilities.value.split(',');
+
+ if (!protocols) {
+ return [];
+ }
+
+ var data = [];
+ $(protocols).each(function() {
+ data.push({id: this.valueOf(), name: this.valueOf(), description: _l('label.lb.protocol.' + this.valueOf())});
+ });
+
+ protocolCapabilities = $.grep(
+ lbService.capability,
+ function(capability) {
+ return (capability.name == 'SslTermination' && (capability.value == 'true' || capability.value == true));
+ }
+ )[0];
+
+ if (!protocolCapabilities) {
+ return data;
+ }
+
+ var protocols = protocolCapabilities.value.split(',');
+
+ if (!protocols) {
+ return data;
+ }
+
+ $(protocols).each(function() {
+ data.push({id: 'ssl', name: 'ssl', description: _l('label.lb.protocol.ssl')});
+ });
+
+ return data;
+ }
+
})(cloudStack, jQuery);
diff --git a/ui/scripts/regions.js b/ui/scripts/regions.js
index 16b891f78b5..ff50bff09e5 100644
--- a/ui/scripts/regions.js
+++ b/ui/scripts/regions.js
@@ -159,6 +159,9 @@
return false;
}
+ }, {
+ path: 'regions.NCC',
+ label: 'label.ncc'
}],
actions: {
edit: {
@@ -258,6 +261,7 @@
}
}
},
+
GSLB: {
id: 'GSLB',
type: 'select',
@@ -1021,6 +1025,224 @@
}
}
}
+ },
+
+ NCC: {
+ id: 'NCC',
+ type: 'select',
+ title: 'NCC',
+ listView: {
+ id: 'NCC',
+ label: 'label.ncc',
+
+ fields: {
+ uuid: {
+ label: 'label.id'
+ },
+ ipaddress: {
+ label: 'label.ipaddress'
+ },
+ numretries: {
+ label: 'label.numretries'
+ }
+ },
+
+ actions: {
+ add: {
+ label: 'label.action.register.ncc',
+
+ preFilter: function(args) {
+ var isRegisterButtonShown = false;
+
+ $.ajax({
+ url: createURL('listNetscalerControlCenter'),
+ async: false,
+ success: function(json) {
+ isRegisterButtonShown = json.listNetscalerControlCenter.netscalercontrolcenter ? false : true;
+ }
+ });
+
+ return isRegisterButtonShown;
+ },
+
+ messages: {
+ confirm: function(args) {
+ return 'label.action.register.ncc';
+ },
+ notification: function(args) {
+ return 'label.action.register.ncc';
+ }
+ },
+
+ createForm: {
+ title: 'label.action.register.ncc',
+ fields: {
+ ipaddress: {
+ label: 'label.ipaddress',
+ validation: {
+ required: true
+ }
+ },
+ username: {
+ label: 'label.username',
+ validation : {
+ required: true
+ }
+ },
+ password: {
+ label: 'label.password',
+ isPassword: true,
+ validation : {
+ required: true,
+ }
+ },
+ numretries: {
+ label: 'label.numretries',
+ defaultValue: '2',
+ validation : {
+ required: true,
+ }
+ }
+ }
+ },
+
+ action: function(args) {
+ var $loading = $('<div>').addClass('loading-overlay');
+ $('.system-dashboard-view:visible').prepend($loading);
+
+ var data = {
+ ipaddress: args.data.ipaddress,
+ username: args.data.username,
+ password: args.data.password,
+ numretries: args.data.numretries
+ };
+
+ $.ajax({
+ url: createURL('registerNetscalerControlCenter'),
+ data: data,
+ dataType: 'json',
+ type: "POST",
+ success: function(json) {
+ var jid = json.registernetscalercontrolcenterresponse.jobid;
+ var registerNetscalerControlCenterIntervalID = setInterval(function() {
+ $.ajax({
+ url: createURL("queryAsyncJobResult&jobId=" + jid),
+ dataType: "json",
+ success: function(json) {
+ var result = json.queryasyncjobresultresponse;
+ if (result.jobstatus == 0) {
+ return; //Job has not completed
+ } else {
+ clearInterval(registerNetscalerControlCenterIntervalID);
+ if (result.jobstatus == 1) {
+ cloudStack.dialog.notice({
+ message: 'message.register.succeeded'
+ });
+ $loading.remove();
+ } else if (result.jobstatus == 2) {
+ cloudStack.dialog.notice({
+ message: _l('message.register.failed') + ' ' + _s(result.jobresult.errortext)
+ });
+ $loading.remove();
+ }
+ }
+ },
+ error: function(XMLHttpResponse) {
+ cloudStack.dialog.notice({
+ message: _l('message.register.failed') + ' ' + parseXMLHttpResponse(XMLHttpResponse)
+ });
+ $loading.remove();
+ }
+ });
+ }, g_queryAsyncJobResultInterval);
+ },
+ error: function(XMLHttpResponse) {
+ cloudStack.dialog.notice({
+ message: _l('message.register.failed') + ' ' + parseXMLHttpResponse(XMLHttpResponse)
+ });
+ $loading.remove();
+ }
+ });
+ },
+
+ notification: {
+ poll: pollAsyncJobResult
+ }
+ }
+ },
+
+ dataProvider: function(args) {
+ $.ajax({
+ url: createURL('listNetscalerControlCenter'),
+ success: function(json) {
+ var item = json.listNetscalerControlCenter.netscalercontrolcenter ? json.listNetscalerControlCenter.netscalercontrolcenter : null;
+ args.response.success({
+ data: item
+ });
+ }
+ });
+ },
+
+ detailView: {
+ name: 'label.ncc.details',
+ actions: {
+ remove: {
+ label: 'label.ncc.delete',
+ messages: {
+ confirm: function(args) {
+ return 'message.ncc.delete.confirm';
+ },
+ notification: function(args) {
+ return 'label.ncc.delete';
+ }
+ },
+ action: function(args) {
+ var data = {
+ id: args.context.NCC[0].uuid
+ };
+ $.ajax({
+ url: createURL("deleteNetscalerControlCenter"),
+ data: data,
+ success: function(json) {
+ var status = json.deleteNetscalerControlCenter ? json.deleteNetscalerControlCenter.success : null;
+ args.response.success({
+ data: status
+ });
+ }
+ });
+ },
+ }
+ },
+ tabs: {
+ details: {
+ title: 'label.details',
+ fields: [{
+ uuid: {
+ label: 'label.id'
+ }
+ }, {
+ ipaddress: {
+ label: 'label.ipaddress'
+ },
+ numretries: {
+ label: 'label.numretries',
+ },
+ }],
+ dataProvider: function(args) {
+ $.ajax({
+ url: createURL('listNetscalerControlCenter'),
+ success: function(json) {
+ var item = json.listNetscalerControlCenter.netscalercontrolcenter ? json.listNetscalerControlCenter.netscalercontrolcenter[0] : null;
+ args.response.success({
+ data: item
+ });
+ }
+ });
+ }
+ }
+ }
+ }
+ }
}
}
};
diff --git a/ui/scripts/roles.js b/ui/scripts/roles.js
index eae088fafa8..01700dfc9a5 100644
--- a/ui/scripts/roles.js
+++ b/ui/scripts/roles.js
@@ -171,6 +171,28 @@
context: context,
noSelect: true,
noHeaderActionsColumn: true,
+ selectPermission: {
+ action: function(args){
+ $.ajax({
+ url: createURL("updateRolePermission"),
+ data: {
+ roleid: args.roleid,
+ ruleid: args.ruleid,
+ permission: args.permission
+ },
+ dataType: "json",
+ async: true,
+ success: function(json) {
+ $(window).trigger('cloudStack.fullRefresh');
+ },
+ error: function(json) {
+ cloudStack.dialog.notice({
+ message: 'message.role.update.fail'
+ });
+ }
+ });
+ }
+ },
reorder: {
moveDrag: {
action: function(args) {
@@ -193,6 +215,7 @@
});
$.ajax({
+ type: 'POST',
url: createURL('updateRolePermission'),
data: {
roleid: rule.roleid,
diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js
index 45b3239a76a..655aee9fb93 100644
--- a/ui/scripts/sharedFunctions.js
+++ b/ui/scripts/sharedFunctions.js
@@ -1225,6 +1225,8 @@ cloudStack.converters = {
return _l('label.secondary.storage.vm');
case 19:
return _l('label.gpu');
+ case 90:
+ return _l('label.num.cpu.cores');
}
},
diff --git a/ui/scripts/storage.js b/ui/scripts/storage.js
index 9638f1e5e2a..639f8a98b7c 100644
--- a/ui/scripts/storage.js
+++ b/ui/scripts/storage.js
@@ -813,13 +813,18 @@
},
name: {
label: 'label.name'
+ },
+ asyncBackup: {
+ label: 'label.async.backup',
+ isBoolean: true
}
}
},
action: function(args) {
var data = {
volumeId: args.context.volumes[0].id,
- quiescevm: (args.data.quiescevm == 'on' ? true: false)
+ quiescevm: (args.data.quiescevm == 'on' ? true: false),
+ asyncBackup: (args.data.asyncBackup == 'on' ? true: false)
};
if (args.data.name != null && args.data.name.length > 0) {
$.extend(data, {
@@ -1706,6 +1711,11 @@
array1.push("&maxiops=" + todb(maxIops));
}
}
+ //if original disk size > new disk size
+ if ((args.context.volumes[0].type == "ROOT")
+ && (args.context.volumes[0].size > (newSize * (1024 * 1024 * 1024)))) {
+ return args.response.error('message.volume.root.shrink.disk.size');
+ }
$.ajax({
diff --git a/ui/scripts/system.js b/ui/scripts/system.js
old mode 100644
new mode 100755
index 9cff5956a1e..e912f3b3ce8
--- a/ui/scripts/system.js
+++ b/ui/scripts/system.js
@@ -54,6 +54,7 @@
$.ajax({
url: createURL('listDomains'),
data: {
+ details: 'min',
listAll: true
},
success: function (json) {
@@ -78,6 +79,7 @@
url: createURL('listDomains'),
data: {
id: data.domainid,
+ details: 'min',
listAll: true
},
success: function (json) {
@@ -552,6 +554,7 @@
$.ajax({
url: createURL('listDomains'),
data: {
+ details: 'min',
listAll: true
},
success: function (json) {
@@ -1852,6 +1855,7 @@
$.ajax({
url: createURL('listDomains'),
data: {
+ details: 'min',
listAll: true
},
success: function (json) {
@@ -2854,8 +2858,8 @@
$.ajax({
url: createURL("listInternalLoadBalancerVMs&zoneid=" + selectedZoneObj.id + "&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("")),
success: function (json) {
- var items = json.listinternallbvmssresponse.internalloadbalancervm ?
- json.listinternallbvmssresponse.internalloadbalancervm:[];
+ var items = json.listinternallbvmsresponse.internalloadbalancervm ?
+ json.listinternallbvmsresponse.internalloadbalancervm:[];
$(items).map(function (index, item) {
routers.push(item);
@@ -2865,8 +2869,8 @@
$.ajax({
url: createURL("listInternalLoadBalancerVMs&zoneid=" + selectedZoneObj.id + "&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("") + "&projectid=-1"),
success: function (json) {
- var items = json.listinternallbvmssresponse.internalloadbalancervm ?
- json.listinternallbvmssresponse.internalloadbalancervm:[];
+ var items = json.listinternallbvmsresponse.internalloadbalancervm ?
+ json.listinternallbvmsresponse.internalloadbalancervm:[];
$(items).map(function (index, item) {
routers.push(item);
@@ -3024,7 +3028,7 @@
dataType: "json",
async: false,
success: function (json) {
- var items = json.listinternallbvmssresponse.internalloadbalancervm;
+ var items = json.listinternallbvmsresponse.internalloadbalancervm;
if (items != null && items.length > 0) {
return items[0];
}
@@ -3157,7 +3161,7 @@
dataType: 'json',
async: true,
success: function (json) {
- var jsonObj = json.listinternallbvmssresponse.internalloadbalancervm[0];
+ var jsonObj = json.listinternallbvmsresponse.internalloadbalancervm[0];
addExtraPropertiesToRouterInstanceObject(jsonObj);
args.response.success({
actionFilter: internallbinstanceActionfilter,
@@ -3209,7 +3213,7 @@
dataType: 'json',
async: true,
success: function (json) {
- var jsonObj = json.listinternallbvmssresponse.internalloadbalancervm[0].nic;
+ var jsonObj = json.listinternallbvmsresponse.internalloadbalancervm[0].nic;
args.response.success({
actionFilter: internallbinstanceActionfilter,
@@ -6146,127 +6150,6 @@
}
},
-
- // MidoNet provider detailView
- midoNet: {
- id: 'midoNet',
- label: 'label.midoNet',
- isMaximized: true,
- type: 'detailView',
- fields: {
- name: {
- label: 'label.name'
- },
- //ipaddress: { label: 'label.ip.address' },
- state: {
- label: 'label.status',
- indicator: {
- 'Enabled': 'on'
- }
- }
- },
- tabs: {
- details: {
- title: 'label.network',
- fields:[ {
- name: {
- label: 'label.name'
- }
- },
- {
- id: {
- label: 'label.id'
- },
- state: {
- label: 'label.state'
- },
- physicalnetworkid: {
- label: 'label.physical.network.ID'
- },
- destinationphysicalnetworkid: {
- label: 'label.destination.physical.network.id'
- },
- supportedServices: {
- label: 'label.supported.services'
- }
- }],
- dataProvider: function (args) {
- refreshNspData("MidoNet");
- args.response.success({
- actionFilter: virtualRouterProviderActionFilter,
- data: $.extend(nspMap[ "midoNet"], {
- supportedServices: nspMap[ "midoNet"].servicelist.join(', ')
- })
- });
- }
- }
- },
- actions: {
- enable: {
- label: 'label.enable.provider',
- action: function (args) {
- $.ajax({
- url: createURL("updateNetworkServiceProvider&id=" + nspMap[ "midoNet"].id + "&state=Enabled"),
- dataType: "json",
- success: function (json) {
- var jid = json.updatenetworkserviceproviderresponse.jobid;
- args.response.success({
- _custom: {
- jobId: jid,
- getUpdatedItem: function (json) {
- $(window).trigger('cloudStack.fullRefresh');
- }
- }
- });
- }
- });
- },
- messages: {
- confirm: function (args) {
- return 'message.confirm.enable.provider';
- },
- notification: function () {
- return 'label.enable.provider';
- }
- },
- notification: {
- poll: pollAsyncJobResult
- }
- },
- disable: {
- label: 'label.disable.provider',
- action: function (args) {
- $.ajax({
- url: createURL("updateNetworkServiceProvider&id=" + nspMap[ "midoNet"].id + "&state=Disabled"),
- dataType: "json",
- success: function (json) {
- var jid = json.updatenetworkserviceproviderresponse.jobid;
- args.response.success({
- _custom: {
- jobId: jid,
- getUpdatedItem: function (json) {
- $(window).trigger('cloudStack.fullRefresh');
- }
- }
- });
- }
- });
- },
- messages: {
- confirm: function (args) {
- return 'message.confirm.disable.provider';
- },
- notification: function () {
- return 'label.disable.provider';
- }
- },
- notification: {
- poll: pollAsyncJobResult
- }
- }
- }
- },
-
//ovs
Ovs: {
id: 'ovsProviders',
@@ -7893,7 +7776,11 @@
},
select: function (args) {
$.ajax({
- url: createURL("listDomains&listAll=true"),
+ url: createURL('listDomains'),
+ data: {
+ listAll: true,
+ details: 'min'
+ },
dataType: "json",
async: false,
success: function (json) {
@@ -8136,6 +8023,80 @@
notification: {
poll: pollAsyncJobResult
}
+ },
+ enableHA: {
+ label: 'label.ha.enable',
+ action: function (args) {
+ var data = {
+ zoneid: args.context.physicalResources[0].id
+ };
+ $.ajax({
+ url: createURL("enableHAForZone"),
+ data: data,
+ success: function (json) {
+ var jid = json.enablehaforzoneresponse.jobid;
+ args.response.success({
+ _custom: {
+ jobId: jid,
+ getActionFilter: function () {
+ return zoneActionfilter;
+ }
+ }
+ });
+ },
+ error: function (json) {
+ args.response.error(parseXMLHttpResponse(json));
+ }
+ });
+ },
+ messages: {
+ confirm: function (args) {
+ return 'label.ha.enable';
+ },
+ notification: function (args) {
+ return 'label.ha.enable';
+ }
+ },
+ notification: {
+ poll: pollAsyncJobResult
+ }
+ },
+ disableHA: {
+ label: 'label.ha.disable',
+ action: function (args) {
+ var data = {
+ zoneid: args.context.physicalResources[0].id
+ };
+ $.ajax({
+ url: createURL("disableHAForZone"),
+ data: data,
+ success: function (json) {
+ var jid = json.disablehaforzoneresponse.jobid;
+ args.response.success({
+ _custom: {
+ jobId: jid,
+ getActionFilter: function () {
+ return zoneActionfilter;
+ }
+ }
+ });
+ },
+ error: function (json) {
+ args.response.error(parseXMLHttpResponse(json));
+ }
+ });
+ },
+ messages: {
+ confirm: function (args) {
+ return 'label.ha.disable';
+ },
+ notification: function (args) {
+ return 'label.ha.disable';
+ }
+ },
+ notification: {
+ poll: pollAsyncJobResult
+ }
}
},
tabs: {
@@ -13324,7 +13285,11 @@
dependsOn: 'isDedicated',
select: function (args) {
$.ajax({
- url: createURL("listDomains&listAll=true"),
+ url: createURL('listDomains'),
+ data: {
+ listAll: true,
+ details: 'min'
+ },
dataType: "json",
async: false,
success: function (json) {
@@ -13542,7 +13507,11 @@
},
select: function (args) {
$.ajax({
- url: createURL("listDomains&listAll=true"),
+ url: createURL('listDomains'),
+ data: {
+ listAll: true,
+ details: 'min'
+ },
dataType: "json",
async: false,
success: function (json) {
@@ -14143,7 +14112,11 @@
dependsOn: 'isDedicated',
select: function (args) {
$.ajax({
- url: createURL("listDomains&listAll=true"),
+ url: createURL('listDomains'),
+ data: {
+ listAll: true,
+ details: 'min'
+ },
dataType: "json",
async: false,
success: function (json) {
@@ -14714,7 +14687,11 @@
},
select: function (args) {
$.ajax({
- url: createURL("listDomains&listAll=true"),
+ url: createURL('listDomains'),
+ data: {
+ listAll: true,
+ details: 'min'
+ },
dataType: "json",
async: false,
success: function (json) {
@@ -14980,8 +14957,81 @@
notification: {
poll: pollAsyncJobResult
}
+ },
+ enableHA: {
+ label: 'label.ha.enable',
+ action: function (args) {
+ var data = {
+ clusterid: args.context.clusters[0].id
+ };
+ $.ajax({
+ url: createURL("enableHAForCluster"),
+ data: data,
+ success: function (json) {
+ var jid = json.enablehaforclusterresponse.jobid;
+ args.response.success({
+ _custom: {
+ jobId: jid,
+ getActionFilter: function () {
+ return clusterActionfilter;
+ }
+ }
+ });
+ },
+ error: function (json) {
+ args.response.error(parseXMLHttpResponse(json));
+ }
+ });
+ },
+ messages: {
+ confirm: function (args) {
+ return 'label.ha.enable';
+ },
+ notification: function (args) {
+ return 'label.ha.enable';
+ }
+ },
+ notification: {
+ poll: pollAsyncJobResult
+ }
+ },
+ disableHA: {
+ label: 'label.ha.disable',
+ action: function (args) {
+ var data = {
+ clusterid: args.context.clusters[0].id
+ };
+ $.ajax({
+ url: createURL("disableHAForCluster"),
+ data: data,
+ success: function (json) {
+ var jid = json.disablehaforclusterresponse.jobid;
+ args.response.success({
+ _custom: {
+ jobId: jid,
+ getActionFilter: function () {
+ return clusterActionfilter;
+ }
+ }
+ });
+ },
+ error: function (json) {
+ args.response.error(parseXMLHttpResponse(json));
+ }
+ });
+ },
+ messages: {
+ confirm: function (args) {
+ return 'label.ha.disable';
+ },
+ notification: function (args) {
+ return 'label.ha.disable';
+ }
+ },
+ notification: {
+ poll: pollAsyncJobResult
+ }
}
-
},
tabs: {
@@ -15699,7 +15749,11 @@
dependsOn: 'isDedicated',
select: function (args) {
$.ajax({
- url: createURL("listDomains&listAll=true"),
+ url: createURL('listDomains'),
+ data: {
+ listAll: true,
+ details: 'min'
+ },
dataType: "json",
success: function (json) {
var domainObjs = json.listdomainsresponse.domain;
@@ -16008,7 +16062,10 @@
array1.push("&hosttags=" + todb(args.data.hosttags));
if (args.data.oscategoryid != null && args.data.oscategoryid.length > 0)
- array1.push("&osCategoryId=" + args.data.oscategoryid);
+ array1.push("&osCategoryId=" + args.data.oscategoryid);
+
+ if (args.data.annotation != null && args.data.annotation.length > 0)
+ array1.push("&annotation=" + args.data.annotation);
$.ajax({
url: createURL("updateHost&id=" + args.context.hosts[0].id + array1.join("")),
@@ -16045,7 +16102,11 @@
},
select: function (args) {
$.ajax({
- url: createURL("listDomains&listAll=true"),
+ url: createURL('listDomains'),
+ data: {
+ listAll: true,
+ details: 'min'
+ },
dataType: "json",
async: false,
success: function (json) {
@@ -16379,6 +16440,168 @@
}
},
+ blankHAForHost: {
+ label: '',
+ action: function (args) {
+ }
+ },
+
+ configureHAForHost: {
+ label: 'label.ha.configure',
+ messages: {
+ confirm: function (args) {
+ return 'label.ha.configure';
+ },
+ notification: function (args) {
+ return 'label.ha.configure';
+ }
+ },
+ createForm: {
+ title: 'label.ha.configure',
+ fields: {
+ provider: {
+ label: 'label.ha.provider',
+ validation: {
+ required: true
+ },
+ select: function (args) {
+ $.ajax({
+ url: createURL('listHostHAProviders'),
+ data: {'hypervisor': args.context.hosts[0].hypervisor},
+ dataType: 'json',
+ success: function (json) {
+ var response = json.listhosthaprovidersresponse;
+ var items = [];
+ items.push({
+ id: '',
+ description: _l('')
+ });
+ if (response.haprovider) {
+ $.each(response.haprovider, function (idx, item) {
+ items.push({
+ id: item.haprovider,
+ description: item.haprovider
+ });
+ });
+ }
+ args.response.success({
+ data: items
+ });
+ },
+ error: function (json) {
+ args.response.error(parseXMLHttpResponse(json));
+ }
+ });
+ }
+ }
+ }
+ },
+ action: function (args) {
+ var data = args.data;
+ data.hostid = args.context.hosts[0].id;
+ $.ajax({
+ url: createURL('configureHAForHost'),
+ data: data,
+ dataType: 'json',
+ success: function (json) {
+ var jid = json.configurehaforhostresponse.jobid;
+ args.response.success({
+ _custom: {
+ jobId: jid,
+ getActionFilter: function () {
+ return hostActionfilter;
+ }
+ }
+ });
+ },
+ error: function (json) {
+ args.response.error(parseXMLHttpResponse(json));
+ }
+ });
+ },
+ notification: {
+ poll: pollAsyncJobResult
+ }
+ },
+
+ enableHA: {
+ label: 'label.ha.enable',
+ action: function (args) {
+ var data = {
+ hostid: args.context.hosts[0].id,
+ };
+ $.ajax({
+ url: createURL("enableHAForHost"),
+ data: data,
+ success: function (json) {
+ var jid = json.enablehaforhostresponse.jobid;
+ args.response.success({
+ _custom: {
+ jobId: jid,
+ getActionFilter: function () {
+ return hostActionfilter;
+ }
+ }
+ });
+ },
+ error: function (json) {
+ args.response.error(parseXMLHttpResponse(json));
+ }
+
+ });
+ },
+ messages: {
+ confirm: function (args) {
+ return 'label.ha.enable';
+ },
+ notification: function (args) {
+ return 'label.ha.enable';
+ }
+ },
+ notification: {
+ poll: pollAsyncJobResult
+ }
+ },
+
+ disableHA: {
+ label: 'label.ha.disable',
+ action: function (args) {
+ var data = {
+ hostid: args.context.hosts[0].id,
+ };
+ $.ajax({
+ url: createURL("disableHAForHost"),
+ data: data,
+ success: function (json) {
+ var jid = json.disablehaforhostresponse.jobid;
+ args.response.success({
+ _custom: {
+ jobId: jid,
+ getActionFilter: function () {
+ return hostActionfilter;
+ }
+ }
+ });
+ },
+ error: function (json) {
+ args.response.error(parseXMLHttpResponse(json));
+ }
+
+ });
+ },
+ messages: {
+ confirm: function (args) {
+ return 'label.ha.disable';
+ },
+ notification: function (args) {
+ return 'label.ha.disable';
+ }
+ },
+ notification: {
+ poll: pollAsyncJobResult
+ }
+ },
+
blankOutOfBandManagement: {
label: '',
action: function (args) {
@@ -16445,6 +16668,10 @@
id: 'ipmitool',
description: 'ipmitool - ipmitool based shell driver'
});
+ items.push({
+ id: 'nestedcloudstack',
+ description: 'nested-cloudstack - controls host that is a VM in a parent cloudstack (testing purposes only)'
+ });
args.response.success({
data: items
});
@@ -16713,6 +16940,9 @@
if (host.outofbandmanagement == null || !host.outofbandmanagement.enabled) {
hiddenTabs.push("outofbandmanagement");
}
+ if (host.hostha == null || (host.hypervisor != 'KVM' && host.hypervisor != 'Simulator')) {
+ hiddenTabs.push("ha");
+ }
return hiddenTabs;
},
tabs: {
@@ -16761,6 +16991,12 @@
hypervisorversion: {
label: 'label.hypervisor.version'
},
+ hastate: {
+ label: 'label.ha.state'
+ },
+ haprovider: {
+ label: 'label.ha.provider'
+ },
hosttags: {
label: 'label.host.tags',
isEditable: true,
@@ -16840,11 +17076,22 @@
ipaddress: {
label: 'label.ip.address'
},
+ annotation: {
+ label: 'label.annotation',
+ isEditable: true
+ },
+ lastannotated: {
+ label: 'label.last.annotated',
+ converter: cloudStack.converters.toLocalDate
+ },
+ username: {
+ label: 'label.annotated.by'
+ },
disconnected: {
label: 'label.last.disconnected'
- },
- cpusockets: {
- label: 'label.number.of.cpu.sockets'
+ },
+ cpusockets: {
+ label: 'label.number.of.cpu.sockets'
}
}, {
@@ -16867,6 +17114,16 @@
item.powerstate = item.outofbandmanagement.powerstate;
}
+ if (item && item.hostha) {
+ item.hastate = item.hostha.hastate;
+ item.haprovider = item.hostha.haprovider;
+ item.haenabled = item.hostha.haenable;
+ }
+
+ item.annotation = item.annotation;
+ item.lastannotated = item.lastannotated;
+ item.username = item.username;
+
$.ajax({
url: createURL("listDedicatedHosts&hostid=" + args.context.hosts[0].id),
dataType: "json",
@@ -16898,6 +17155,39 @@
}
},
+ ha: {
+ title: 'label.ha',
+ fields: {
+ haenable: {
+ label: 'label.ha.enabled',
+ converter: cloudStack.converters.toBooleanText
+ },
+ hastate: {
+ label: 'label.ha.state'
+ },
+ haprovider: {
+ label: 'label.ha.provider'
+ },
+ },
+ dataProvider: function (args) {
+ $.ajax({
+ url: createURL("listHosts&id=" + args.context.hosts[0].id),
+ dataType: "json",
+ async: true,
+ success: function (json) {
+ var host = json.listhostsresponse.host[0];
+ var hostha = {};
+ if (host && host.hostha) {
+ hostha = host.hostha;
+ }
+ args.response.success({
+ data: hostha
+ });
+ }
+ });
+ }
+ },
+
outofbandmanagement: {
title: 'label.outofbandmanagement',
fields: {
@@ -21186,6 +21476,12 @@
allowedActions.push("disableOutOfBandManagement");
}
+ if (jsonObj.hasOwnProperty('resourcedetails') && jsonObj['resourcedetails'].hasOwnProperty('resourceHAEnabled') && jsonObj['resourcedetails']['resourceHAEnabled'] == 'false') {
+ allowedActions.push("enableHA");
+ } else {
+ allowedActions.push("disableHA");
+ }
+
return allowedActions;
}
@@ -21277,6 +21573,12 @@
allowedActions.push("disableOutOfBandManagement");
}
+ if (jsonObj.hasOwnProperty('resourcedetails') && jsonObj['resourcedetails'].hasOwnProperty('resourceHAEnabled') && jsonObj['resourcedetails']['resourceHAEnabled'] == 'false') {
+ allowedActions.push("enableHA");
+ } else {
+ allowedActions.push("disableHA");
+ }
+
return allowedActions;
}
@@ -21313,6 +21615,14 @@
allowedActions.push("remove");
}
+ allowedActions.push("blankHAForHost");
+ allowedActions.push("configureHAForHost");
+ if (jsonObj.hasOwnProperty("hostha") && jsonObj.hostha.haenable) {
+ allowedActions.push("disableHA");
+ } else {
+ allowedActions.push("enableHA");
+ }
+
allowedActions.push("blankOutOfBandManagement");
allowedActions.push("configureOutOfBandManagement");
if (jsonObj.hasOwnProperty("outofbandmanagement") && jsonObj.outofbandmanagement.enabled) {
@@ -21472,11 +21782,66 @@
nspMap[id]: {
};
+ if (id == "netscaler") {
+ var netscalerControlCenter = null;
+
+ $.ajax({
+ url: createURL("listNetscalerControlCenter"),
+ dataType: "json",
+ async: false,
+ success: function(json) {
+ var items = json.listNetscalerControlCenter.netscalercontrolcenter;
+ if (items != null && items.length > 0) {
+ netscalerControlCenter = items[0];
+ }
+ }
+ });
+ }
+
+ if (netscalerControlCenter != null) {
+ if (jsonObj.state == undefined) {
+ $.ajax({
+ url: createURL("addNetworkServiceProvider&name=Netscaler&physicalnetworkid=" + selectedPhysicalNetworkObj.id),
+ dataType: "json",
+ async: true,
+ success: function (json) {
+ var jobId = json.addnetworkserviceproviderresponse.jobid;
+ var addNetscalerProviderIntervalID = setInterval(function () {
+ $.ajax({
+ url: createURL("queryAsyncJobResult&jobId=" + jobId),
+ dataType: "json",
+ success: function (json) {
+ var result = json.queryasyncjobresultresponse;
+ if (result.jobstatus == 0) {
+ return; //Job has not completed
+ } else {
+ clearInterval(addNetscalerProviderIntervalID);
+ if (result.jobstatus == 1) {
+ nspMap[ "netscaler"] = result.jobresult.networkserviceprovider;
+ addExternalLoadBalancer(args, selectedPhysicalNetworkObj, "addNetscalerLoadBalancer", "addnetscalerloadbalancerresponse", "netscalerloadbalancer");
+ } else if (result.jobstatus == 2) {
+ alert("addNetworkServiceProvider&name=Netscaler failed. Error: " + _s(result.jobresult.errortext));
+ }
+ }
+ },
+ error: function (XMLHttpResponse) {
+ var errorMsg = parseXMLHttpResponse(XMLHttpResponse);
+ alert("addNetworkServiceProvider&name=Netscaler failed. Error: " + errorMsg);
+ }
+ });
+ },
+ g_queryAsyncJobResultInterval);
+ }
+ });
+ jsonObj.state = "Disabled";
+ }
+ }
+
if (jsonObj.state) {
- if (jsonObj.state == "Enabled")
- allowedActions.push("disable"); else if (jsonObj.state == "Disabled")
- allowedActions.push("enable");
- allowedActions.push("destroy");
+ if (jsonObj.state == "Enabled")
+ allowedActions.push("disable"); else if (jsonObj.state == "Disabled")
+ allowedActions.push("enable");
+ allowedActions.push("destroy");
}
allowedActions.push('add');
@@ -21534,9 +21899,6 @@
case "Netscaler":
nspMap[ "netscaler"] = items[i];
break;
- case "MidoNet":
- nspMap[ "midoNet"] = items[i];
- break;
case "BaremetalDhcpProvider":
nspMap[ "BaremetalDhcpProvider"] = items[i];
break;
@@ -21636,12 +21998,6 @@
state: nspMap.securityGroups ? nspMap.securityGroups.state: 'Disabled'
});
} else if (selectedZoneObj.networktype == "Advanced") {
- nspHardcodingArray.push({
- id: 'midoNet',
- name: 'MidoNet',
- state: nspMap.midoNet ? nspMap.midoNet.state: 'Disabled'
- });
-
nspHardcodingArray.push({
id: 'nuageVsp',
name: 'Nuage Vsp',
diff --git a/ui/scripts/ui-custom/ca.js b/ui/scripts/ui-custom/ca.js
new file mode 100644
index 00000000000..c5298292371
--- /dev/null
+++ b/ui/scripts/ui-custom/ca.js
@@ -0,0 +1,53 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+(function($, cloudStack) {
+ $(window).bind('cloudStack.ready', function() {
+ var caCert = "";
+ var downloadCaCert = function() {
+ var blob = new Blob([caCert], {type: 'application/x-x509-ca-cert'});
+ var filename = "cloud-ca.pem";
+ if(window.navigator.msSaveOrOpenBlob) {
+ window.navigator.msSaveBlob(blob, filename);
+ } else{
+ var elem = window.document.createElement('a');
+ elem.href = window.URL.createObjectURL(blob);
+ elem.download = filename;
+ document.body.appendChild(elem)
+ elem.click();
+ document.body.removeChild(elem);
+ }
+ };
+
+ $.ajax({
+ url: createURL('listCaCertificate'),
+ success: function(json) {
+ caCert = json.listcacertificateresponse.cacertificates.certificate;
+ if (caCert) {
+ var $caCertDownloadButton = $('<div>').addClass('cacert-download');
+ $caCertDownloadButton.append($('<span>').addClass('icon').html(' ').attr('title', 'Download CA Certificate'));
+ $caCertDownloadButton.click(function() {
+ downloadCaCert();
+ });
+ $('#header .controls .view-switcher:last').after($caCertDownloadButton);
+ }
+ },
+ error: function(data) {
+ }
+ });
+ });
+}(jQuery, cloudStack));
diff --git a/ui/scripts/ui-custom/saml.js b/ui/scripts/ui-custom/saml.js
index 391e7f885c7..1879bdc83bf 100644
--- a/ui/scripts/ui-custom/saml.js
+++ b/ui/scripts/ui-custom/saml.js
@@ -81,7 +81,10 @@
option.data("userId", accounts[i].userId);
option.data("domainId", accounts[i].domainId);
option.val(accounts[i].userId + '/' + accounts[i].domainId);
- option.html(accounts[i].accountName + "/" + accounts[i].domainName);
+ option.html(accounts[i].accountName + accounts[i].domainPath);
+ if (accounts[i].domainName == 'ROOT') {
+ option.append('ROOT');
+ }
option.appendTo($domainSelect);
}
var currentAccountDomain = g_userid + '/' + g_domainid;
diff --git a/ui/scripts/ui-custom/zoneChart.js b/ui/scripts/ui-custom/zoneChart.js
index 415d24f5260..188a9e74838 100644
--- a/ui/scripts/ui-custom/zoneChart.js
+++ b/ui/scripts/ui-custom/zoneChart.js
@@ -386,6 +386,9 @@
},
19: {
name: _l('GPU')
+ },
+ 90: {
+ name: _l('label.num.cpu.cores')
}
};
diff --git a/ui/scripts/ui/widgets/multiEdit.js b/ui/scripts/ui/widgets/multiEdit.js
index 3e88b929394..48d597e6859 100755
--- a/ui/scripts/ui/widgets/multiEdit.js
+++ b/ui/scripts/ui/widgets/multiEdit.js
@@ -31,6 +31,7 @@
var $item = $('<div>').addClass('data-item');
var multiRule = data;
var reorder = options.reorder;
+ var selectPermission = options.selectPermission;
$item.append($('<table>').append($('<tbody>')));
$tr = $('<tr>').appendTo($item.find('tbody'));
@@ -189,10 +190,34 @@
return $(this).val() == data[fieldName];
});
- var matchingValue = $matchingOption.size() ?
- $matchingOption.html() : data[fieldName];
+ if (selectPermission) {
+ // Wrap div to get its html code
+ selectedOptionHtml = $matchingOption.clone().wrap('<div>').parent().html();
+ // Get html code from not matching option
+ $matchingSelect.find('option').each(
+ function() {
+ if ($(this).val() != data[fieldName]){
+ selectedOptionHtml += $(this).clone().wrap('<div>').parent().html();
+ }
+ }
+ );
+ $select = $('<select>');
+ $select.html(selectedOptionHtml);
+ $select.change(function(event) {
+ selectPermission.action({
+ roleid: data['roleid'],
+ ruleid: data['id'],
+ permission: $(this).val()
+ });
+ });
+ $td.append($select);
+ }
+ else {
+ var matchingValue = $matchingOption.size() ?
+ $matchingOption.html() : data[fieldName];
- $td.append($('<span>').html(_s(matchingValue)));
+ $td.append($('<span>').html(_s(matchingValue)));
+ }
} else if (field.addButton && !options.noSelect) {
if (options.multipleAdd) {
$addButton.click(function() {
@@ -862,6 +887,7 @@
var actionPreFilter = args.actionPreFilter;
var readOnlyCheck = args.readOnlyCheck;
var reorder = args.reorder;
+ var selectPermission = args.selectPermission;
var $thead = $('<tr>').appendTo(
$('<thead>').appendTo($inputTable)
@@ -1197,7 +1223,8 @@
preFilter: actionPreFilter,
listView: listView,
tags: tags,
- reorder: reorder
+ reorder: reorder,
+ selectPermission: selectPermission
}
).appendTo($dataBody);
});
diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js
index d1a093ad090..8416d38fd7d 100644
--- a/ui/scripts/vpc.js
+++ b/ui/scripts/vpc.js
@@ -745,12 +745,19 @@
}
},
dataProvider: function(args) {
+ var data = {
+ page: args.page,
+ pageSize: pageSize,
+ networkid: args.context.networks[0].id,
+ listAll: true
+ };
+ var keyword = (((args || {}).filterBy || {}).search || {}).value;
+ if (keyword) {
+ data.keyword = keyword;
+ }
$.ajax({
url: createURL('listLoadBalancers'),
- data: {
- networkid: args.context.networks[0].id,
- listAll: true
- },
+ data: data,
success: function(json) {
var items = json.listloadbalancersresponse.loadbalancer;
if (items != null) {
diff --git a/usage/pom.xml b/usage/pom.xml
index 6ec81650273..864787a68a4 100644
--- a/usage/pom.xml
+++ b/usage/pom.xml
@@ -15,7 +15,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
@@ -113,7 +113,7 @@
<configuration>
<target>
<copy overwrite="true" todir="${basedir}/target/transformed">
- <fileset dir="${basedir}/../client/tomcatconf">
+ <fileset dir="${basedir}/../client/conf">
<include name="**/db.properties.in" />
</fileset>
<globmapper from="*.in" to="*" />
diff --git a/usage/src/com/cloud/usage/UsageServer.java b/usage/src/com/cloud/usage/UsageServer.java
index 246ad06eba6..df3f374cc30 100644
--- a/usage/src/com/cloud/usage/UsageServer.java
+++ b/usage/src/com/cloud/usage/UsageServer.java
@@ -16,19 +16,13 @@
// under the License.
package com.cloud.usage;
-import java.io.File;
-import java.io.FileNotFoundException;
-
import org.apache.commons.daemon.Daemon;
import org.apache.commons.daemon.DaemonContext;
import org.apache.commons.daemon.DaemonInitException;
import org.apache.log4j.Logger;
-import org.apache.log4j.PropertyConfigurator;
-import org.apache.log4j.xml.DOMConfigurator;
import org.springframework.context.support.ClassPathXmlApplicationContext;
-import org.springframework.util.Log4jConfigurer;
-import com.cloud.utils.PropertiesUtil;
+import com.cloud.utils.LogUtils;
import com.cloud.utils.component.ComponentContext;
public class UsageServer implements Daemon {
@@ -83,28 +77,7 @@ public void destroy() {
}
static private void initLog4j() {
- File file = PropertiesUtil.findConfigFile("log4j-cloud.xml");
- if (file != null) {
- System.out.println("log4j configuration found at " + file.getAbsolutePath());
- try {
- Log4jConfigurer.initLogging(file.getAbsolutePath());
- } catch (FileNotFoundException e) {
- s_logger.info("[ignored] log initialisation ;)" + e.getLocalizedMessage(), e);
- }
- DOMConfigurator.configureAndWatch(file.getAbsolutePath());
-
- } else {
- file = PropertiesUtil.findConfigFile("log4j-cloud.properties");
- if (file != null) {
- System.out.println("log4j configuration found at " + file.getAbsolutePath());
- try {
- Log4jConfigurer.initLogging(file.getAbsolutePath());
- } catch (FileNotFoundException e) {
- s_logger.info("[ignored] log properties initialization :)" + e.getLocalizedMessage(), e);
- }
- PropertyConfigurator.configureAndWatch(file.getAbsolutePath());
- }
- }
+ LogUtils.initLog4j("log4j-cloud.xml");
}
}
diff --git a/usage/src/com/cloud/usage/parser/StorageUsageParser.java b/usage/src/com/cloud/usage/parser/StorageUsageParser.java
index fccd00ca478..03aa97b847d 100644
--- a/usage/src/com/cloud/usage/parser/StorageUsageParser.java
+++ b/usage/src/com/cloud/usage/parser/StorageUsageParser.java
@@ -181,8 +181,11 @@ private static void createUsageRecord(long zoneId, int type, long runningTime, D
usageDesc += "Snapshot ";
break;
}
- // Create the usage record
- usageDesc += "Id:" + storageId + " Size:" + size + "VirtualSize:" + virtualSize;
+ //Create the usage record
+ usageDesc += "Id:" + storageId + " Size:" + size;
+ if (type != StorageTypes.SNAPSHOT) {
+ usageDesc += " VirtualSize:" + virtualSize;
+ }
//ToDo: get zone id
UsageVO usageRecord =
diff --git a/usage/test/resources/db.properties b/usage/test/resources/db.properties
index e8e94121fe1..eabc445c208 100644
--- a/usage/test/resources/db.properties
+++ b/usage/test/resources/db.properties
@@ -17,7 +17,7 @@
# management server clustering parameters, change cluster.node.IP to the machine IP address
-# in which the management server(Tomcat) is running
+# in which the management server is running
cluster.node.IP=127.0.0.1
cluster.servlet.port=9090
diff --git a/utils/conf/db.properties b/utils/conf/db.properties
index 4182811a6a6..2fd6910368a 100644
--- a/utils/conf/db.properties
+++ b/utils/conf/db.properties
@@ -19,7 +19,7 @@
# management server clustering parameters, change cluster.node.IP to the machine IP address
-# in which the management server(Tomcat) is running
+# in which the management server is running
cluster.node.IP=127.0.0.1
cluster.servlet.port=9090
region.id=1
diff --git a/utils/pom.xml b/utils/pom.xml
index ba8a70ccb36..9989afc084e 100755
--- a/utils/pom.xml
+++ b/utils/pom.xml
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
@@ -35,6 +35,11 @@
<artifactId>cloud-framework-managed-context</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-framework-ca</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
@@ -71,6 +76,10 @@
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcpkix-jdk15on</artifactId>
+ </dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
@@ -85,7 +94,11 @@
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
- <artifactId>aws-java-sdk</artifactId>
+ <artifactId>aws-java-sdk-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.amazonaws</groupId>
+ <artifactId>aws-java-sdk-s3</artifactId>
</dependency>
<dependency>
<groupId>log4j</groupId>
@@ -147,6 +160,10 @@
<groupId>xerces</groupId>
<artifactId>xmlParserAPIs</artifactId>
</exclusion>
+ <exclusion>
+ <groupId>commons-beanutils</groupId>
+ <artifactId>commons-beanutils-core</artifactId>
+ </exclusion>
</exclusions>
</dependency>
<dependency>
@@ -157,7 +174,7 @@
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
- <version>3.5</version>
+ <version>3.6</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
diff --git a/utils/src/main/java/com/cloud/utils/SerialVersionUID.java b/utils/src/main/java/com/cloud/utils/SerialVersionUID.java
index b45e028a550..4dd5add28dd 100644
--- a/utils/src/main/java/com/cloud/utils/SerialVersionUID.java
+++ b/utils/src/main/java/com/cloud/utils/SerialVersionUID.java
@@ -67,4 +67,5 @@
public static final long AffinityConflictException = Base | 0x2a;
public static final long NioConnectionException = Base | 0x2c;
public static final long TaskExecutionException = Base | 0x2d;
+ public static final long SnapshotBackupException = Base | 0x2e;
}
diff --git a/utils/src/main/java/com/cloud/utils/StringUtils.java b/utils/src/main/java/com/cloud/utils/StringUtils.java
index 9554e87c35e..6ada2ad60bd 100644
--- a/utils/src/main/java/com/cloud/utils/StringUtils.java
+++ b/utils/src/main/java/com/cloud/utils/StringUtils.java
@@ -21,10 +21,12 @@
import java.nio.charset.Charset;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -320,4 +322,10 @@ public static String mapToString(final Map<String, String> map) {
}
return listOfChunks;
}
+
+ public static String shuffleCSVList(final String csvList) {
+ List<String> list = csvTagsToList(csvList);
+ Collections.shuffle(list, new Random(System.nanoTime()));
+ return join(list, ",");
+ }
}
diff --git a/utils/src/main/java/com/cloud/utils/UriUtils.java b/utils/src/main/java/com/cloud/utils/UriUtils.java
index 631c629aed3..8805891cd2a 100644
--- a/utils/src/main/java/com/cloud/utils/UriUtils.java
+++ b/utils/src/main/java/com/cloud/utils/UriUtils.java
@@ -30,6 +30,7 @@
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import java.util.StringTokenizer;
@@ -55,6 +56,7 @@
import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.exception.CloudRuntimeException;
+import com.google.common.base.Strings;
public class UriUtils {
@@ -391,4 +393,52 @@ public static InputStream getInputStreamFromUrl(String url, String user, String
return null;
}
}
+
+ /**
+ * Expands a given vlan URI to a list of vlan IDs
+ * @param vlanAuthority the URI part without the vlan:// scheme
+ * @return returns list of vlan integer ids
+ */
+ public static List<Integer> expandVlanUri(final String vlanAuthority) {
+ final List<Integer> expandedVlans = new ArrayList<>();
+ if (Strings.isNullOrEmpty(vlanAuthority)) {
+ return expandedVlans;
+ }
+ for (final String vlanPart: vlanAuthority.split(",")) {
+ if (Strings.isNullOrEmpty(vlanPart)) {
+ continue;
+ }
+ final String[] range = vlanPart.split("-");
+ if (range.length == 2) {
+ Integer start = NumbersUtil.parseInt(range[0], -1);
+ Integer end = NumbersUtil.parseInt(range[1], -1);
+ if (start <= end && end > -1 && start > -1) {
+ while (start <= end) {
+ expandedVlans.add(start++);
+ }
+ }
+ } else {
+ final Integer value = NumbersUtil.parseInt(range[0], -1);
+ if (value > -1) {
+ expandedVlans.add(value);
+ }
+ }
+ }
+ return expandedVlans;
+ }
+
+ /**
+ * Checks if given vlan URI authorities overlap
+ * @param vlanRange1
+ * @param vlanRange2
+ * @return true if they overlap
+ */
+ public static boolean checkVlanUriOverlap(final String vlanRange1, final String vlanRange2) {
+ final List<Integer> vlans1 = expandVlanUri(vlanRange1);
+ final List<Integer> vlans2 = expandVlanUri(vlanRange2);
+ if (vlans1 == null || vlans2 == null) {
+ return true;
+ }
+ return !Collections.disjoint(vlans1, vlans2);
+ }
}
diff --git a/utils/src/main/java/com/cloud/utils/exception/TaskExecutionException.java b/utils/src/main/java/com/cloud/utils/exception/TaskExecutionException.java
index be639baeaeb..635874e9c81 100644
--- a/utils/src/main/java/com/cloud/utils/exception/TaskExecutionException.java
+++ b/utils/src/main/java/com/cloud/utils/exception/TaskExecutionException.java
@@ -25,7 +25,7 @@
* Used by the Task class to wrap-up its exceptions.
*/
public class TaskExecutionException extends Exception {
- private static final long serialVersionUID = SerialVersionUID.NioConnectionException;
+ private static final long serialVersionUID = SerialVersionUID.TaskExecutionException;
protected int csErrorCode;
diff --git a/utils/src/main/java/com/cloud/utils/net/NetUtils.java b/utils/src/main/java/com/cloud/utils/net/NetUtils.java
index 4972070ea66..c28739a91bd 100644
--- a/utils/src/main/java/com/cloud/utils/net/NetUtils.java
+++ b/utils/src/main/java/com/cloud/utils/net/NetUtils.java
@@ -44,6 +44,7 @@
import org.apache.commons.lang.SystemUtils;
import org.apache.commons.net.util.SubnetUtils;
import org.apache.commons.validator.routines.InetAddressValidator;
+import org.apache.commons.validator.routines.RegexValidator;
import org.apache.log4j.Logger;
import com.cloud.utils.IteratorUtil;
@@ -1179,6 +1180,23 @@ public static boolean validateGuestCidr(final String cidr) {
return false;
}
+ public static boolean isValidMac(final String macAddr) {
+ RegexValidator mv = new RegexValidator("^(?:[0-9a-f]{1,2}([-:\\.]))(?:[0-9a-f]{1,2}\\1){4}[0-9a-f]{1,2}$", false);
+ return mv.isValid(macAddr);
+ }
+
+ public static boolean isUnicastMac(final String macAddr) {
+ String std = standardizeMacAddress(macAddr);
+ if(std == null) {
+ return false;
+ }
+ long stdl = mac2Long(std);
+ // libvirt refuses to attach a mac address that is multicast, as defined
+ // by the least significant bit of the first octet of the mac.
+ long mask = 0x1l << 40l;
+ return ((stdl & mask) == mask) ? false : true;
+ }
+
public static boolean verifyInstanceName(final String instanceName) {
//instance name for cloudstack vms shouldn't contain - and spaces
if (instanceName.contains("-") || instanceName.contains(" ") || instanceName.contains("+")) {
@@ -1456,6 +1474,15 @@ public static String standardizeIp6Address(final String ip6Addr) {
}
}
+ public static String standardizeMacAddress(final String macAddr) {
+ if (!isValidMac(macAddr)) {
+ return null;
+ }
+ String norm = macAddr.replace('.', ':');
+ norm = norm.replace('-', ':');
+ return long2Mac(mac2Long(norm));
+ }
+
public static String standardizeIp6Cidr(final String ip6Cidr){
try {
return IPv6Network.fromString(ip6Cidr).toString();
diff --git a/utils/src/main/java/com/cloud/utils/nio/Link.java b/utils/src/main/java/com/cloud/utils/nio/Link.java
index 02ffaab4e02..7848d5330a3 100644
--- a/utils/src/main/java/com/cloud/utils/nio/Link.java
+++ b/utils/src/main/java/com/cloud/utils/nio/Link.java
@@ -19,20 +19,6 @@
package com.cloud.utils.nio;
-import com.cloud.utils.PropertiesUtil;
-import com.cloud.utils.db.DbProperties;
-import org.apache.cloudstack.utils.security.SSLUtils;
-import org.apache.log4j.Logger;
-
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLEngineResult;
-import javax.net.ssl.SSLEngineResult.HandshakeStatus;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@@ -44,8 +30,27 @@
import java.nio.channels.SocketChannel;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
+import java.security.SecureRandom;
import java.util.concurrent.ConcurrentLinkedQueue;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLEngineResult.HandshakeStatus;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+
+import org.apache.cloudstack.framework.ca.CAService;
+import org.apache.cloudstack.utils.security.KeyStoreUtils;
+import org.apache.cloudstack.utils.security.SSLUtils;
+import org.apache.log4j.Logger;
+
+import com.cloud.utils.PropertiesUtil;
+import com.cloud.utils.exception.CloudRuntimeException;
+
/**
*/
public class Link {
@@ -62,7 +67,6 @@
private boolean _gotFollowingPacket;
private SSLEngine _sslEngine;
- public static final String keystoreFile = "/cloudmanagementserver.keystore";
public Link(InetSocketAddress addr, NioConnection connection) {
_addr = addr;
@@ -97,49 +101,6 @@ public void setSSLEngine(SSLEngine sslEngine) {
_sslEngine = sslEngine;
}
- /**
- * No user, so comment it out.
- *
- * Static methods for reading from a channel in case
- * you need to add a client that doesn't require nio.
- * @param ch channel to read from.
- * @param bytebuffer to use.
- * @return bytes read
- * @throws IOException if not read to completion.
- public static byte[] read(SocketChannel ch, ByteBuffer buff) throws IOException {
- synchronized(buff) {
- buff.clear();
- buff.limit(4);
-
- while (buff.hasRemaining()) {
- if (ch.read(buff) == -1) {
- throw new IOException("Connection closed with -1 on reading size.");
- }
- }
-
- buff.flip();
-
- int length = buff.getInt();
- ByteArrayOutputStream output = new ByteArrayOutputStream(length);
- WritableByteChannel outCh = Channels.newChannel(output);
-
- int count = 0;
- while (count < length) {
- buff.clear();
- int read = ch.read(buff);
- if (read < 0) {
- throw new IOException("Connection closed with -1 on reading data.");
- }
- count += read;
- buff.flip();
- outCh.write(buff);
- }
-
- return output.toByteArray();
- }
- }
- */
-
private static void doWrite(SocketChannel ch, ByteBuffer[] buffers, SSLEngine sslEngine) throws IOException {
SSLSession sslSession = sslEngine.getSession();
ByteBuffer pkgBuf = ByteBuffer.allocate(sslSession.getPacketBufferSize() + 40);
@@ -404,48 +365,88 @@ public synchronized void schedule(Task task) throws ClosedChannelException {
_connection.scheduleTask(task);
}
- public static SSLContext initSSLContext(boolean isClient) throws GeneralSecurityException, IOException {
- InputStream stream;
- SSLContext sslContext = null;
- KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
- TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
- KeyStore ks = KeyStore.getInstance("JKS");
- TrustManager[] tms;
+ public static KeyStore loadKeyStore(final InputStream stream, final char[] passphrase) throws GeneralSecurityException, IOException {
+ final KeyStore ks = KeyStore.getInstance("JKS");
+ ks.load(stream, passphrase);
+ return ks;
+ }
+
+ public static SSLEngine initServerSSLEngine(final CAService caService, final String clientAddress) throws GeneralSecurityException, IOException {
+ final SSLContext sslContext = SSLUtils.getSSLContext();
+ if (caService != null) {
+ return caService.createSSLEngine(sslContext, clientAddress);
+ }
+ s_logger.error("CA service is not configured, by-passing CA manager to create SSL engine");
+ char[] passphrase = KeyStoreUtils.defaultKeystorePassphrase;
+ final KeyStore ks = loadKeyStore(NioConnection.class.getResourceAsStream("/cloud.keystore"), passphrase);
+ final KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+ final TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
+ kmf.init(ks, passphrase);
+ tmf.init(ks);
+ sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
+ return sslContext.createSSLEngine();
+ }
+
+ public static SSLContext initManagementSSLContext(final CAService caService) throws GeneralSecurityException, IOException {
+ if (caService == null) {
+ throw new CloudRuntimeException("CAService is not available to load/get management server keystore");
+ }
+ final KeyStore ks = caService.getManagementKeyStore();
+ char[] passphrase = caService.getKeyStorePassphrase();
- File confFile = PropertiesUtil.findConfigFile("db.properties");
- if (null != confFile && !isClient) {
- final String pass = DbProperties.getDbProperties().getProperty("db.cloud.keyStorePassphrase");
- char[] passphrase = "vmops.com".toCharArray();
+ final TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
+ tmf.init(ks);
+ final TrustManager[] tms = tmf.getTrustManagers();
+
+ final KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+ kmf.init(ks, passphrase);
+
+ final SSLContext sslContext = SSLUtils.getSSLContext();
+ sslContext.init(kmf.getKeyManagers(), tms, new SecureRandom());
+ return sslContext;
+ }
+
+ public static SSLContext initClientSSLContext() throws GeneralSecurityException, IOException {
+ char[] passphrase = KeyStoreUtils.defaultKeystorePassphrase;
+ File confFile = PropertiesUtil.findConfigFile("agent.properties");
+ if (confFile != null) {
+ s_logger.info("Conf file found: " + confFile.getAbsolutePath());
+ final String pass = PropertiesUtil.loadFromFile(confFile).getProperty(KeyStoreUtils.passphrasePropertyName);
if (pass != null) {
passphrase = pass.toCharArray();
}
- String confPath = confFile.getParent();
- String keystorePath = confPath + keystoreFile;
+ }
+
+ InputStream stream = null;
+ if (confFile != null) {
+ final String keystorePath = confFile.getParent() + "/" + KeyStoreUtils.defaultKeystoreFile;
if (new File(keystorePath).exists()) {
stream = new FileInputStream(keystorePath);
- } else {
- s_logger.warn("SSL: Fail to find the generated keystore. Loading fail-safe one to continue.");
- stream = NioConnection.class.getResourceAsStream("/cloud.keystore");
- passphrase = "vmops.com".toCharArray();
}
- ks.load(stream, passphrase);
- stream.close();
- kmf.init(ks, passphrase);
- tmf.init(ks);
+ }
+
+ final KeyStore ks = loadKeyStore(stream, passphrase);
+ final TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
+ tmf.init(ks);
+ TrustManager[] tms;
+ if (stream != null) {
+ // This enforces a two-way SSL authentication
tms = tmf.getTrustManagers();
} else {
- ks.load(null, null);
- kmf.init(ks, null);
- tms = new TrustManager[1];
- tms[0] = new TrustAllManager();
+ // This enforces a one-way SSL authentication
+ tms = new TrustManager[]{new TrustAllManager()};
+ s_logger.warn("Failed to load keystore, using trust all manager");
}
- sslContext = SSLUtils.getSSLContext();
- sslContext.init(kmf.getKeyManagers(), tms, null);
- if (s_logger.isTraceEnabled()) {
- s_logger.trace("SSL: SSLcontext has been initialized");
+ if (stream != null) {
+ stream.close();
}
+ final KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+ kmf.init(ks, passphrase);
+
+ final SSLContext sslContext = SSLUtils.getSSLContext();
+ sslContext.init(kmf.getKeyManagers(), tms, new SecureRandom());
return sslContext;
}
@@ -498,8 +499,9 @@ private static boolean doHandshakeUnwrap(final SocketChannel socketChannel, fina
try {
result = sslEngine.unwrap(peerNetData, peerAppData);
peerNetData.compact();
- } catch (SSLException sslException) {
- s_logger.error("SSL error occurred while processing unwrap data: " + sslException.getMessage());
+ } catch (final SSLException sslException) {
+ s_logger.error(String.format("SSL error caught during unwrap data: %s, for local address=%s, remote address=%s. The client may have invalid ca-certificates.",
+ sslException.getMessage(), socketChannel.getLocalAddress(), socketChannel.getRemoteAddress()));
sslEngine.closeOutbound();
return true;
}
@@ -539,8 +541,9 @@ private static boolean doHandshakeWrap(final SocketChannel socketChannel, final
SSLEngineResult result = null;
try {
result = sslEngine.wrap(myAppData, myNetData);
- } catch (SSLException sslException) {
- s_logger.error("SSL error occurred while processing wrap data: " + sslException.getMessage());
+ } catch (final SSLException sslException) {
+ s_logger.error(String.format("SSL error caught during wrap data: %s, for local address=%s, remote address=%s.",
+ sslException.getMessage(), socketChannel.getLocalAddress(), socketChannel.getRemoteAddress()));
sslEngine.closeOutbound();
return true;
}
diff --git a/utils/src/main/java/com/cloud/utils/nio/NioClient.java b/utils/src/main/java/com/cloud/utils/nio/NioClient.java
index dc4f670de12..1c29b0c1a2d 100644
--- a/utils/src/main/java/com/cloud/utils/nio/NioClient.java
+++ b/utils/src/main/java/com/cloud/utils/nio/NioClient.java
@@ -56,7 +56,7 @@ protected void init() throws IOException {
_clientConnection.connect(peerAddr);
_clientConnection.configureBlocking(false);
- final SSLContext sslContext = Link.initSSLContext(true);
+ final SSLContext sslContext = Link.initClientSSLContext();
SSLEngine sslEngine = sslContext.createSSLEngine(_host, _port);
sslEngine.setUseClientMode(true);
sslEngine.setEnabledProtocols(SSLUtils.getSupportedProtocols(sslEngine.getEnabledProtocols()));
diff --git a/utils/src/main/java/com/cloud/utils/nio/NioConnection.java b/utils/src/main/java/com/cloud/utils/nio/NioConnection.java
index ce032462ec2..30000cf618b 100644
--- a/utils/src/main/java/com/cloud/utils/nio/NioConnection.java
+++ b/utils/src/main/java/com/cloud/utils/nio/NioConnection.java
@@ -19,13 +19,8 @@
package com.cloud.utils.nio;
-import com.cloud.utils.concurrency.NamedThreadFactory;
-import com.cloud.utils.exception.NioConnectionException;
-import org.apache.cloudstack.utils.security.SSLUtils;
-import org.apache.log4j.Logger;
+import static com.cloud.utils.AutoCloseableUtil.closeAutoCloseable;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
import java.io.IOException;
import java.net.ConnectException;
import java.net.InetSocketAddress;
@@ -49,7 +44,14 @@
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
-import static com.cloud.utils.AutoCloseableUtil.closeAutoCloseable;
+import javax.net.ssl.SSLEngine;
+
+import org.apache.cloudstack.framework.ca.CAService;
+import org.apache.cloudstack.utils.security.SSLUtils;
+import org.apache.log4j.Logger;
+
+import com.cloud.utils.concurrency.NamedThreadFactory;
+import com.cloud.utils.exception.NioConnectionException;
/**
* NioConnection abstracts the NIO socket operations. The Java implementation
@@ -70,6 +72,7 @@
protected String _name;
protected ExecutorService _executor;
protected ExecutorService _sslHandshakeExecutor;
+ protected CAService caService;
public NioConnection(final String name, final int port, final int workers, final HandlerFactory factory) {
_name = name;
@@ -81,6 +84,10 @@ public NioConnection(final String name, final int port, final int workers, final
_sslHandshakeExecutor = Executors.newCachedThreadPool(new NamedThreadFactory(name + "-SSLHandshakeHandler"));
}
+ public void setCAService(final CAService caService) {
+ this.caService = caService;
+ }
+
public void start() throws NioConnectionException {
_todos = new ArrayList<ChangeRequest>();
@@ -124,7 +131,7 @@ public boolean isStartup() {
public Boolean call() throws NioConnectionException {
while (_isRunning) {
try {
- _selector.select(100);
+ _selector.select(50);
// Someone is ready for I/O, get the ready keys
final Set<SelectionKey> readyKeys = _selector.selectedKeys();
@@ -196,10 +203,8 @@ protected void accept(final SelectionKey key) throws IOException {
final SSLEngine sslEngine;
try {
- final SSLContext sslContext = Link.initSSLContext(false);
- sslEngine = sslContext.createSSLEngine();
+ sslEngine = Link.initServerSSLEngine(caService, socketChannel.getRemoteAddress().toString());
sslEngine.setUseClientMode(false);
- sslEngine.setNeedClientAuth(false);
sslEngine.setEnabledProtocols(SSLUtils.getSupportedProtocols(sslEngine.getEnabledProtocols()));
final NioConnection nioConnection = this;
_sslHandshakeExecutor.submit(new Runnable() {
diff --git a/utils/src/main/java/com/cloud/utils/nio/NioServer.java b/utils/src/main/java/com/cloud/utils/nio/NioServer.java
index b655f1838bb..ff54165841e 100644
--- a/utils/src/main/java/com/cloud/utils/nio/NioServer.java
+++ b/utils/src/main/java/com/cloud/utils/nio/NioServer.java
@@ -27,6 +27,7 @@
import java.nio.channels.spi.SelectorProvider;
import java.util.WeakHashMap;
+import org.apache.cloudstack.framework.ca.CAService;
import org.apache.log4j.Logger;
public class NioServer extends NioConnection {
@@ -37,8 +38,9 @@
protected WeakHashMap<InetSocketAddress, Link> _links;
- public NioServer(final String name, final int port, final int workers, final HandlerFactory factory) {
+ public NioServer(final String name, final int port, final int workers, final HandlerFactory factory, final CAService caService) {
super(name, port, workers, factory);
+ setCAService(caService);
_localAddr = null;
_links = new WeakHashMap<InetSocketAddress, Link>(1024);
}
diff --git a/utils/src/main/java/com/cloud/utils/script/Script.java b/utils/src/main/java/com/cloud/utils/script/Script.java
index 76084751417..01f18bda2d2 100644
--- a/utils/src/main/java/com/cloud/utils/script/Script.java
+++ b/utils/src/main/java/com/cloud/utils/script/Script.java
@@ -37,6 +37,7 @@
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
+import org.apache.cloudstack.utils.security.KeyStoreUtils;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.joda.time.Duration;
@@ -202,7 +203,7 @@ public String execute(OutputInterpreter interpreter) {
String[] command = _command.toArray(new String[_command.size()]);
if (_logger.isDebugEnabled()) {
- _logger.debug("Executing: " + buildCommandLine(command));
+ _logger.debug("Executing: " + buildCommandLine(command).split(KeyStoreUtils.defaultKeystoreFile)[0]);
}
try {
diff --git a/utils/src/main/java/com/cloud/utils/ssh/SSHCmdHelper.java b/utils/src/main/java/com/cloud/utils/ssh/SSHCmdHelper.java
index 61d01c4ebd9..10407b65642 100644
--- a/utils/src/main/java/com/cloud/utils/ssh/SSHCmdHelper.java
+++ b/utils/src/main/java/com/cloud/utils/ssh/SSHCmdHelper.java
@@ -22,8 +22,10 @@
import java.io.IOException;
import java.io.InputStream;
+import org.apache.cloudstack.utils.security.KeyStoreUtils;
import org.apache.log4j.Logger;
+import com.google.common.base.Strings;
import com.trilead.ssh2.ChannelCondition;
import com.trilead.ssh2.Session;
@@ -32,6 +34,44 @@
private static final int DEFAULT_CONNECT_TIMEOUT = 180000;
private static final int DEFAULT_KEX_TIMEOUT = 60000;
+ public static class SSHCmdResult {
+ private int returnCode = -1;
+ private String stdOut;
+ private String stdErr;
+
+ public SSHCmdResult(final int returnCode, final String stdOut, final String stdErr) {
+ this.returnCode = returnCode;
+ this.stdOut = stdOut;
+ this.stdErr = stdErr;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("SSH cmd result: return code=%d, stdout=%s, stderr=%s",
+ getReturnCode(), getStdOut().split("-----BEGIN")[0], getStdErr());
+ }
+
+ public boolean isSuccess() {
+ return returnCode == 0;
+ }
+
+ public int getReturnCode() {
+ return returnCode;
+ }
+
+ public void setReturnCode(int returnCode) {
+ this.returnCode = returnCode;
+ }
+
+ public String getStdOut() {
+ return stdOut;
+ }
+
+ public String getStdErr() {
+ return stdErr;
+ }
+ }
+
public static com.trilead.ssh2.Connection acquireAuthorizedConnection(String ip, String username, String password) {
return acquireAuthorizedConnection(ip, 22, username, password);
}
@@ -65,36 +105,41 @@ public static void releaseSshConnection(com.trilead.ssh2.Connection sshConnectio
public static boolean sshExecuteCmd(com.trilead.ssh2.Connection sshConnection, String cmd, int nTimes) {
for (int i = 0; i < nTimes; i++) {
try {
- if (sshExecuteCmdOneShot(sshConnection, cmd))
+ final SSHCmdResult result = sshExecuteCmdOneShot(sshConnection, cmd);
+ if (result.isSuccess()) {
return true;
- } catch (SshException e) {
+ }
+ } catch (SshException ignored) {
continue;
}
}
return false;
}
- public static int sshExecuteCmdWithExitCode(com.trilead.ssh2.Connection sshConnection, String cmd) {
- return sshExecuteCmdWithExitCode(sshConnection, cmd, 3);
- }
-
- public static int sshExecuteCmdWithExitCode(com.trilead.ssh2.Connection sshConnection, String cmd, int nTimes) {
+ public static SSHCmdResult sshExecuteCmdWithResult(com.trilead.ssh2.Connection sshConnection, String cmd, int nTimes) {
for (int i = 0; i < nTimes; i++) {
try {
- return sshExecuteCmdOneShotWithExitCode(sshConnection, cmd);
- } catch (SshException e) {
+ final SSHCmdResult result = sshExecuteCmdOneShot(sshConnection, cmd);
+ if (result.isSuccess()) {
+ return result;
+ }
+ } catch (SshException ignored) {
continue;
}
}
- return -1;
+ return new SSHCmdResult(-1, null, null);
}
public static boolean sshExecuteCmd(com.trilead.ssh2.Connection sshConnection, String cmd) {
return sshExecuteCmd(sshConnection, cmd, 3);
}
- public static int sshExecuteCmdOneShotWithExitCode(com.trilead.ssh2.Connection sshConnection, String cmd) throws SshException {
- s_logger.debug("Executing cmd: " + cmd);
+ public static SSHCmdResult sshExecuteCmdWithResult(com.trilead.ssh2.Connection sshConnection, String cmd) {
+ return sshExecuteCmdWithResult(sshConnection, cmd, 3);
+ }
+
+ public static SSHCmdResult sshExecuteCmdOneShot(com.trilead.ssh2.Connection sshConnection, String cmd) throws SshException {
+ s_logger.debug("Executing cmd: " + cmd.split(KeyStoreUtils.defaultKeystoreFile)[0]);
Session sshSession = null;
try {
sshSession = sshConnection.openSession();
@@ -112,7 +157,8 @@ public static int sshExecuteCmdOneShotWithExitCode(com.trilead.ssh2.Connection s
InputStream stderr = sshSession.getStderr();
byte[] buffer = new byte[8192];
- StringBuffer sbResult = new StringBuffer();
+ StringBuffer sbStdoutResult = new StringBuffer();
+ StringBuffer sbStdErrResult = new StringBuffer();
int currentReadBytes = 0;
while (true) {
@@ -145,27 +191,30 @@ public static int sshExecuteCmdOneShotWithExitCode(com.trilead.ssh2.Connection s
while (stdout.available() > 0) {
currentReadBytes = stdout.read(buffer);
- sbResult.append(new String(buffer, 0, currentReadBytes));
+ sbStdoutResult.append(new String(buffer, 0, currentReadBytes));
}
while (stderr.available() > 0) {
currentReadBytes = stderr.read(buffer);
- sbResult.append(new String(buffer, 0, currentReadBytes));
+ sbStdErrResult.append(new String(buffer, 0, currentReadBytes));
}
}
- String result = sbResult.toString();
- if (result != null && !result.isEmpty())
- s_logger.debug(cmd + " output:" + result);
+ final SSHCmdResult result = new SSHCmdResult(-1, sbStdoutResult.toString(), sbStdErrResult.toString());
+ if (!Strings.isNullOrEmpty(result.getStdOut()) || !Strings.isNullOrEmpty(result.getStdErr())) {
+ s_logger.debug("SSH command: " + cmd.split(KeyStoreUtils.defaultKeystoreFile)[0] + "\nSSH command output:" + result.getStdOut().split("-----BEGIN")[0] + "\n" + result.getStdErr());
+ }
+
// exit status delivery might get delayed
for(int i = 0 ; i<10 ; i++ ) {
Integer status = sshSession.getExitStatus();
if( status != null ) {
- return status;
+ result.setReturnCode(status);
+ return result;
}
Thread.sleep(100);
}
- return -1;
+ return result;
} catch (Exception e) {
s_logger.debug("Ssh executed failed", e);
throw new SshException("Ssh executed failed " + e.getMessage());
@@ -174,8 +223,4 @@ public static int sshExecuteCmdOneShotWithExitCode(com.trilead.ssh2.Connection s
sshSession.close();
}
}
-
- public static boolean sshExecuteCmdOneShot(com.trilead.ssh2.Connection sshConnection, String cmd) throws SshException {
- return sshExecuteCmdOneShotWithExitCode(sshConnection, cmd) == 0;
- }
}
diff --git a/utils/src/main/java/org/apache/cloudstack/utils/security/CertUtils.java b/utils/src/main/java/org/apache/cloudstack/utils/security/CertUtils.java
new file mode 100644
index 00000000000..7e783622c40
--- /dev/null
+++ b/utils/src/main/java/org/apache/cloudstack/utils/security/CertUtils.java
@@ -0,0 +1,252 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.utils.security;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.security.SignatureException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.security.auth.x500.X500Principal;
+
+import org.apache.log4j.Logger;
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x509.BasicConstraints;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.GeneralName;
+import org.bouncycastle.asn1.x509.GeneralNames;
+import org.bouncycastle.asn1.x509.KeyUsage;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.cert.X509v1CertificateBuilder;
+import org.bouncycastle.cert.X509v3CertificateBuilder;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
+import org.bouncycastle.cert.jcajce.JcaX509v1CertificateBuilder;
+import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.openssl.PEMParser;
+import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
+import org.bouncycastle.operator.ContentSigner;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.bouncycastle.util.io.pem.PemObject;
+import org.bouncycastle.util.io.pem.PemReader;
+import org.bouncycastle.util.io.pem.PemWriter;
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+
+import com.google.common.base.Strings;
+
+//import org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure;
+
+public class CertUtils {
+
+ private static final Logger LOG = Logger.getLogger(CertUtils.class);
+
+ public static KeyPair generateRandomKeyPair(final int keySize) throws NoSuchProviderException, NoSuchAlgorithmException {
+ Security.addProvider(new BouncyCastleProvider());
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC");
+ keyPairGenerator.initialize(keySize, new SecureRandom());
+ return keyPairGenerator.generateKeyPair();
+ }
+
+ public static KeyFactory getKeyFactory() {
+ KeyFactory keyFactory = null;
+ try {
+ Security.addProvider(new BouncyCastleProvider());
+ keyFactory = KeyFactory.getInstance("RSA", "BC");
+ } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
+ LOG.error("Unable to create KeyFactory:" + e.getMessage());
+ }
+ return keyFactory;
+ }
+
+ public static X509Certificate pemToX509Certificate(final String pem) throws CertificateException, IOException {
+ final PEMParser pemParser = new PEMParser(new StringReader(pem));
+ return new JcaX509CertificateConverter().setProvider("BC").getCertificate((X509CertificateHolder) pemParser.readObject());
+ }
+
+ public static String x509CertificateToPem(final X509Certificate cert) throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (final JcaPEMWriter pw = new JcaPEMWriter(sw)) {
+ pw.writeObject(cert);
+ pw.flush();
+ }
+ return sw.toString();
+ }
+
+ public static String x509CertificatesToPem(final List<X509Certificate> certificates) throws IOException {
+ if (certificates == null) {
+ return "";
+ }
+ final StringBuilder buffer = new StringBuilder();
+ for (final X509Certificate certificate: certificates) {
+ buffer.append(CertUtils.x509CertificateToPem(certificate));
+ }
+ return buffer.toString();
+ }
+
+ public static PrivateKey pemToPrivateKey(final String pem) throws InvalidKeySpecException, IOException {
+ final PemReader pr = new PemReader(new StringReader(pem));
+ final PemObject pemObject = pr.readPemObject();
+ final KeyFactory keyFactory = getKeyFactory();
+ return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(pemObject.getContent()));
+ }
+
+ public static String privateKeyToPem(final PrivateKey key) throws IOException {
+ final PemObject pemObject = new PemObject("RSA PRIVATE KEY", key.getEncoded());
+ final StringWriter sw = new StringWriter();
+ try (final PemWriter pw = new PemWriter(sw)) {
+ pw.writeObject(pemObject);
+ }
+ return sw.toString();
+ }
+
+ public static PublicKey pemToPublicKey(final String pem) throws InvalidKeySpecException, IOException {
+ final PemReader pr = new PemReader(new StringReader(pem));
+ final PemObject pemObject = pr.readPemObject();
+ final KeyFactory keyFactory = getKeyFactory();
+ return keyFactory.generatePublic(new X509EncodedKeySpec(pemObject.getContent()));
+ }
+
+ public static String publicKeyToPem(final PublicKey key) throws IOException {
+ final PemObject pemObject = new PemObject("PUBLIC KEY", key.getEncoded());
+ final StringWriter sw = new StringWriter();
+ try (final PemWriter pw = new PemWriter(sw)) {
+ pw.writeObject(pemObject);
+ }
+ return sw.toString();
+ }
+
+ public static BigInteger generateRandomBigInt() {
+ return new BigInteger(64, new SecureRandom());
+ }
+
+ public static X509Certificate generateV1Certificate(final KeyPair keyPair,
+ final String subject,
+ final String issuer,
+ final int validityYears,
+ final String signatureAlgorithm) throws CertificateException, NoSuchAlgorithmException, NoSuchProviderException, SignatureException, InvalidKeyException, OperatorCreationException {
+ final DateTime now = DateTime.now(DateTimeZone.UTC);
+ final X509v1CertificateBuilder certBuilder = new JcaX509v1CertificateBuilder(
+ new X500Name(issuer),
+ generateRandomBigInt(),
+ now.minusDays(1).toDate(),
+ now.plusYears(validityYears).toDate(),
+ new X500Name(subject),
+ keyPair.getPublic());
+ final ContentSigner signer = new JcaContentSignerBuilder(signatureAlgorithm).setProvider("BC").build(keyPair.getPrivate());
+ final X509CertificateHolder certHolder = certBuilder.build(signer);
+ return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHolder);
+ }
+
+ public static X509Certificate generateV3Certificate(final X509Certificate caCert,
+ final KeyPair caKeyPair,
+ final PublicKey clientPublicKey,
+ final String subject,
+ final String signatureAlgorithm,
+ final int validityDays,
+ final List<String> dnsNames,
+ final List<String> publicIPAddresses) throws IOException, NoSuchAlgorithmException, CertificateException, NoSuchProviderException, InvalidKeyException, SignatureException, OperatorCreationException {
+
+ final DateTime now = DateTime.now(DateTimeZone.UTC);
+ final BigInteger serial = generateRandomBigInt();
+ final JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
+ final X509v3CertificateBuilder certBuilder;
+ if (caCert == null) {
+ // Generate CA certificate
+ certBuilder = new JcaX509v3CertificateBuilder(
+ new X500Name(subject),
+ serial,
+ now.minusHours(12).toDate(),
+ now.plusDays(validityDays).toDate(),
+ new X500Name(subject),
+ clientPublicKey);
+
+ certBuilder.addExtension(Extension.basicConstraints, true, new BasicConstraints(true));
+ certBuilder.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.keyCertSign | KeyUsage.cRLSign));
+ } else {
+ // Generate client certificate
+ certBuilder = new JcaX509v3CertificateBuilder(
+ caCert,
+ serial,
+ now.minusHours(12).toDate(),
+ now.plusDays(validityDays).toDate(),
+ new X500Principal(subject),
+ clientPublicKey);
+
+ certBuilder.addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(caCert));
+ }
+
+ certBuilder.addExtension(Extension.subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(clientPublicKey));
+
+ final List<ASN1Encodable> subjectAlternativeNames = new ArrayList<ASN1Encodable>();
+ if (publicIPAddresses != null) {
+ for (final String publicIPAddress: publicIPAddresses) {
+ if (Strings.isNullOrEmpty(publicIPAddress)) {
+ continue;
+ }
+ subjectAlternativeNames.add(new GeneralName(GeneralName.iPAddress, publicIPAddress));
+ }
+ }
+ if (dnsNames != null) {
+ for (final String dnsName : dnsNames) {
+ if (Strings.isNullOrEmpty(dnsName)) {
+ continue;
+ }
+ subjectAlternativeNames.add(new GeneralName(GeneralName.dNSName, dnsName));
+ }
+ }
+ if (subjectAlternativeNames.size() > 0) {
+ final GeneralNames subjectAltNames = GeneralNames.getInstance(new DERSequence(subjectAlternativeNames.toArray(new ASN1Encodable[] {})));
+ certBuilder.addExtension(Extension.subjectAlternativeName, false, subjectAltNames);
+ }
+
+ final ContentSigner signer = new JcaContentSignerBuilder(signatureAlgorithm).setProvider("BC").build(caKeyPair.getPrivate());
+ final X509CertificateHolder certHolder = certBuilder.build(signer);
+ final X509Certificate cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHolder);
+ if (caCert != null) {
+ cert.verify(caCert.getPublicKey());
+ } else {
+ cert.verify(caKeyPair.getPublic());
+ }
+ return cert;
+ }
+}
diff --git a/utils/src/main/java/org/apache/cloudstack/utils/security/ChecksumValue.java b/utils/src/main/java/org/apache/cloudstack/utils/security/ChecksumValue.java
new file mode 100644
index 00000000000..e47bf393db2
--- /dev/null
+++ b/utils/src/main/java/org/apache/cloudstack/utils/security/ChecksumValue.java
@@ -0,0 +1,86 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.utils.security;
+
+import java.util.Objects;
+
+import org.apache.commons.lang.StringUtils;
+
+public class ChecksumValue {
+ String checksum;
+ String algorithm = "MD5";
+ public ChecksumValue(String algorithm, String checksum) {
+ this.algorithm = algorithm;
+ this.checksum = checksum;
+ }
+ public ChecksumValue(String digest) {
+ digest = StringUtils.strip(digest);
+ this.algorithm = algorithmFromDigest(digest);
+ this.checksum = stripAlgorithmFromDigest(digest);
+ }
+
+ @Override
+ public String toString() {
+ return '{' + algorithm + '}'+ checksum;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ ChecksumValue that = (ChecksumValue)o;
+ return Objects.equals(getChecksum(), that.getChecksum()) && Objects.equals(getAlgorithm(), that.getAlgorithm());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getChecksum(), getAlgorithm());
+ }
+
+ public String getChecksum() {
+ return checksum;
+ }
+
+ public String getAlgorithm() {
+ return algorithm;
+ }
+
+ private static String stripAlgorithmFromDigest(String digest) {
+ if(StringUtils.isNotEmpty(digest)) {
+ int s = digest.indexOf('{');// only assume a
+ int e = digest.indexOf('}');
+ if (s == 0 && e > s) { // we have an algorithm name of at least 1 char
+ return digest.substring(e+1);
+ }
+ }
+ // we assume digest is alright if there is no algorithm at the start
+ return digest;
+ }
+
+ private static String algorithmFromDigest(String digest) {
+ if(StringUtils.isNotEmpty(digest)) {
+ int s = digest.indexOf('{');
+ int e = digest.indexOf('}');
+ if (s == 0 && e > s+1) { // we have an algorithm name of at least 1 char
+ return digest.substring(s+1,e);
+ } // else if no algoritm
+ } // or if no digest at all
+ return "MD5";
+ }
+}
diff --git a/utils/src/main/java/org/apache/cloudstack/utils/security/DigestHelper.java b/utils/src/main/java/org/apache/cloudstack/utils/security/DigestHelper.java
new file mode 100644
index 00000000000..67adf74189d
--- /dev/null
+++ b/utils/src/main/java/org/apache/cloudstack/utils/security/DigestHelper.java
@@ -0,0 +1,96 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.utils.security;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class DigestHelper {
+
+ public static ChecksumValue digest(String algorithm, InputStream is) throws NoSuchAlgorithmException, IOException {
+ MessageDigest digest = MessageDigest.getInstance(algorithm);
+ ChecksumValue checksum = null;
+ byte[] buffer = new byte[8192];
+ int read = 0;
+ while ((read = is.read(buffer)) > 0) {
+ digest.update(buffer, 0, read);
+ }
+ byte[] md5sum = digest.digest();
+ // TODO make sure this is valid for all types of checksums !?!
+ BigInteger bigInt = new BigInteger(1, md5sum);
+ checksum = new ChecksumValue(digest.getAlgorithm(), getPaddedDigestString(digest,bigInt));
+ return checksum;
+ }
+
+ public static boolean check(String checksum, InputStream is) throws IOException, NoSuchAlgorithmException {
+ ChecksumValue toCheckAgainst = new ChecksumValue(checksum);
+ String algorithm = toCheckAgainst.getAlgorithm();
+ ChecksumValue result = digest(algorithm,is);
+ return result.equals(toCheckAgainst);
+ }
+
+ public static String getPaddedDigest(String algorithm, String inputString) throws NoSuchAlgorithmException {
+ MessageDigest digest = MessageDigest.getInstance(algorithm);
+ String checksum;
+ digest.reset();
+ BigInteger pwInt = new BigInteger(1, digest.digest(inputString.getBytes()));
+ return getPaddedDigestString(digest, pwInt);
+ }
+
+ private static String getPaddedDigestString(MessageDigest digest, BigInteger pwInt) {
+ String checksum;
+ String pwStr = pwInt.toString(16);
+ // we have half byte string representation, so
+ int padding = 2*digest.getDigestLength() - pwStr.length();
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < padding; i++) {
+ sb.append('0'); // make sure the MD5 password is 32 digits long
+ }
+ sb.append(pwStr);
+ checksum = sb.toString();
+ return checksum;
+ }
+
+ static final Map<String, Integer> paddingLengths = creatPaddingLengths();
+
+ private static final Map<String, Integer> creatPaddingLengths() {
+ Map<String, Integer> map = new HashMap<>();
+ map.put("MD5", 32);
+ map.put("SHA-1", 40);
+ map.put("SHA-224", 56);
+ map.put("SHA-256", 64);
+ map.put("SHA-384", 96);
+ map.put("SHA-512", 128);
+ return map;
+ }
+
+ public static boolean isAlgorithmSupported(String checksum) {
+ ChecksumValue toCheckAgainst = new ChecksumValue(checksum);
+ String algorithm = toCheckAgainst.getAlgorithm();
+ try {
+ MessageDigest.getInstance(algorithm);
+ } catch (NoSuchAlgorithmException e) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/utils/src/main/java/org/apache/cloudstack/utils/security/KeyStoreUtils.java b/utils/src/main/java/org/apache/cloudstack/utils/security/KeyStoreUtils.java
new file mode 100644
index 00000000000..8259d77d4ff
--- /dev/null
+++ b/utils/src/main/java/org/apache/cloudstack/utils/security/KeyStoreUtils.java
@@ -0,0 +1,41 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.utils.security;
+
+public class KeyStoreUtils {
+
+ public static String defaultTmpKeyStoreFile = "/tmp/tmp.jks";
+ public static String defaultKeystoreFile = "cloud.jks";
+ public static String defaultPrivateKeyFile = "cloud.key";
+ public static String defaultCsrFile = "cloud.csr";
+ public static String defaultCertFile = "cloud.crt";
+ public static String defaultCaCertFile = "cloud.ca.crt";
+ public static char[] defaultKeystorePassphrase = "vmops.com".toCharArray();
+
+ public static String certNewlineEncoder = "^";
+ public static String certSpaceEncoder = "~";
+
+ public static String keyStoreSetupScript = "keystore-setup";
+ public static String keyStoreImportScript = "keystore-cert-import";
+ public static String passphrasePropertyName = "keystore.passphrase";
+
+ public static String sshMode = "ssh";
+ public static String agentMode = "agent";
+}
diff --git a/utils/src/main/java/org/apache/cloudstack/utils/security/SSLUtils.java b/utils/src/main/java/org/apache/cloudstack/utils/security/SSLUtils.java
index c1fc2d606f2..8016f5a1916 100644
--- a/utils/src/main/java/org/apache/cloudstack/utils/security/SSLUtils.java
+++ b/utils/src/main/java/org/apache/cloudstack/utils/security/SSLUtils.java
@@ -39,7 +39,24 @@
}
set.add(s);
}
- return (String[]) set.toArray(new String[set.size()]);
+ return set.toArray(new String[set.size()]);
+ }
+
+ /**
+ * It returns recommended protocols that are considered secure.
+ */
+ public static String[] getRecommendedProtocols() {
+ return new String[] { "TLSv1", "TLSv1.1", "TLSv1.2" };
+ }
+
+ /**
+ * It returns recommended ciphers that are considered secure.
+ */
+ public static String[] getRecommendedCiphers() {
+ return new String[] { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
+ "TLS_RSA_WITH_AES_128_GCM_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+ "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
+ "TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_256_CBC_SHA256", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" };
}
public static String[] getSupportedCiphers() throws NoSuchAlgorithmException {
@@ -49,10 +66,10 @@
}
public static SSLContext getSSLContext() throws NoSuchAlgorithmException {
- return SSLContext.getInstance("TLSv1");
+ return SSLContext.getInstance("TLSv1.2");
}
public static SSLContext getSSLContext(String provider) throws NoSuchAlgorithmException, NoSuchProviderException {
- return SSLContext.getInstance("TLSv1", provider);
+ return SSLContext.getInstance("TLSv1.2", provider);
}
}
diff --git a/utils/src/test/java/com/cloud/utils/StringUtilsTest.java b/utils/src/test/java/com/cloud/utils/StringUtilsTest.java
index 3619ede84b2..e8e62b0a75e 100644
--- a/utils/src/test/java/com/cloud/utils/StringUtilsTest.java
+++ b/utils/src/test/java/com/cloud/utils/StringUtilsTest.java
@@ -20,6 +20,8 @@
package com.cloud.utils;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertNotEquals;
import java.nio.charset.Charset;
@@ -250,4 +252,15 @@ public void listToCsvTags() {
assertEquals("a,b,c", StringUtils.listToCsvTags(Arrays.asList("a","b", "c")));
assertEquals("", StringUtils.listToCsvTags(new ArrayList<String>()));
}
+
+ @Test
+ public void testShuffleCSVList() {
+ String input = "one,two,three,four,five,six,seven,eight,nine,ten";
+ String output = StringUtils.shuffleCSVList(input);
+ assertFalse(input.equals(output));
+
+ input = "only-one";
+ output = StringUtils.shuffleCSVList("only-one");
+ assertTrue(input.equals(output));
+ }
}
diff --git a/utils/src/test/java/com/cloud/utils/UriUtilsTest.java b/utils/src/test/java/com/cloud/utils/UriUtilsTest.java
index d2fd9976558..b8d951db340 100644
--- a/utils/src/test/java/com/cloud/utils/UriUtilsTest.java
+++ b/utils/src/test/java/com/cloud/utils/UriUtilsTest.java
@@ -20,9 +20,12 @@
package com.cloud.utils;
import junit.framework.Assert;
-
import org.junit.Test;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
public class UriUtilsTest {
@Test
public void encodeURIComponent() {
@@ -57,4 +60,45 @@ public void getUpdateUri() {
//XXX: Interesting cases not covered:
// * port is ignored and left out from the return value
}
+
+ @Test
+ public void expandVlanEmpty() {
+ List<Integer> vlans = UriUtils.expandVlanUri("");
+ Assert.assertTrue(vlans.size() == 0);
+ }
+
+ @Test
+ public void expandVlanSingleValue() {
+ List<Integer> vlans = UriUtils.expandVlanUri("10");
+ Assert.assertTrue(vlans.size() == 1);
+ Assert.assertEquals(vlans, Collections.singletonList(10));
+ }
+
+ @Test
+ public void expandVlanValidRange() {
+ List<Integer> vlans = UriUtils.expandVlanUri("10-12,14,17,40-43");
+ Assert.assertEquals(vlans, Arrays.asList(10,11,12,14,17,40,41,42,43));
+ }
+
+ @Test
+ public void expandVlanInvalidRange() {
+ List<Integer> vlans = UriUtils.expandVlanUri("10-,12-14,-4,5-2");
+ Assert.assertEquals(vlans, Arrays.asList(10,12,13,14));
+ }
+
+ @Test
+ public void testVlanUriOverlap() {
+ Assert.assertTrue(UriUtils.checkVlanUriOverlap("10-30,45,50,12,31", "10"));
+ Assert.assertTrue(UriUtils.checkVlanUriOverlap("10-30,45,50,12,31", "32,33-44,30-31"));
+ Assert.assertTrue(UriUtils.checkVlanUriOverlap("10-30", "25-35"));
+ }
+
+ @Test
+ public void testVlanUriNoOverlap() {
+ Assert.assertFalse(UriUtils.checkVlanUriOverlap("10-30,45,50,12,31", null));
+ Assert.assertFalse(UriUtils.checkVlanUriOverlap("10-30,45,50,12,31", ""));
+ Assert.assertFalse(UriUtils.checkVlanUriOverlap("10-30,45,50,12,31", "32"));
+ Assert.assertFalse(UriUtils.checkVlanUriOverlap("10,22,111", "12"));
+ Assert.assertFalse(UriUtils.checkVlanUriOverlap("100-200", "30-40,50,201-250"));
+ }
}
diff --git a/utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java b/utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java
index fb769dedd13..eaa9c29088e 100644
--- a/utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java
+++ b/utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java
@@ -178,6 +178,24 @@ public void testIsValidIp6Cidr() {
assertFalse(NetUtils.isValidIp6Cidr("1234:5678::1"));
}
+ @Test
+ public void testIsValidMacAddr() {
+ assertTrue(NetUtils.isValidMac("ee:12:34:5:32:ff"));
+ assertTrue(NetUtils.isValidMac("ee.12.34.5.32.ff"));
+ assertTrue(NetUtils.isValidMac("ee-12-34-5-32-ff"));
+ assertFalse(NetUtils.isValidMac("aa.12:34:5:32:ff"));
+ assertFalse(NetUtils.isValidMac("gg.gg:gg:gg:gg:gg"));
+ }
+
+ @Test
+ public void testIsUnicastMac() {
+
+ assertTrue(NetUtils.isUnicastMac("ee:12:34:5:32:ff"));
+ assertFalse(NetUtils.isUnicastMac("ff:12:34:5:32:ff"));
+ assertFalse(NetUtils.isUnicastMac("01:12:34:5:32:ff"));
+ assertTrue(NetUtils.isUnicastMac("00:ff:ff:ff:ff:ff"));
+ }
+
@Test
public void testIsValidIpv6() {
assertTrue(NetUtils.isValidIpv6("fc00::1"));
diff --git a/utils/src/test/java/com/cloud/utils/security/SSLUtilsTest.java b/utils/src/test/java/com/cloud/utils/security/SSLUtilsTest.java
new file mode 100644
index 00000000000..625b538d7f2
--- /dev/null
+++ b/utils/src/test/java/com/cloud/utils/security/SSLUtilsTest.java
@@ -0,0 +1,79 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package com.cloud.utils.security;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import org.apache.cloudstack.utils.security.SSLUtils;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Spy;
+import org.mockito.runners.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class SSLUtilsTest {
+
+ @Spy
+ private SSLUtils spySSLUtils;
+
+ @Test
+ public void getRecommendedProtocolsTest() {
+ ArrayList<String> protocolsList = new ArrayList<>(Arrays.asList(spySSLUtils.getRecommendedProtocols()));
+ verifyProtocols(protocolsList);
+ }
+
+ @Test
+ public void getRecommendedCiphers() {
+ String[] expectedCiphers = { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
+ "TLS_RSA_WITH_AES_128_GCM_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+ "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
+ "TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_256_CBC_SHA256", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" };
+ Assert.assertArrayEquals(expectedCiphers, spySSLUtils.getRecommendedCiphers());
+ }
+
+ @Test
+ public void getSSLContextTest() throws NoSuchAlgorithmException {
+ Assert.assertEquals("TLSv1.2", spySSLUtils.getSSLContext().getProtocol());
+ }
+
+ @Test
+ public void getSSLContextTestStringAsParameter() throws NoSuchAlgorithmException, NoSuchProviderException {
+ Assert.assertEquals("TLSv1.2", spySSLUtils.getSSLContext("SunJSSE").getProtocol());
+ }
+
+ @Test
+ public void getSupportedProtocolsTest() {
+ ArrayList<String> protocolsList = new ArrayList<>(Arrays.asList(spySSLUtils.getSupportedProtocols(new String[] { "TLSv1", "TLSv1.1", "TLSv1.2", "SSLv3", "SSLv2Hello" })));
+ verifyProtocols(protocolsList);
+ }
+
+ private void verifyProtocols(ArrayList<String> protocolsList) {
+ Assert.assertTrue(protocolsList.contains("TLSv1"));
+ Assert.assertTrue(protocolsList.contains("TLSv1.1"));
+ Assert.assertTrue(protocolsList.contains("TLSv1.2"));
+ Assert.assertFalse(protocolsList.contains("SSLv3"));
+ Assert.assertFalse(protocolsList.contains("SSLv2Hello"));
+ }
+
+}
diff --git a/utils/src/test/java/com/cloud/utils/testcase/NioTest.java b/utils/src/test/java/com/cloud/utils/testcase/NioTest.java
index 894aa1adc88..0a9deea1a9d 100644
--- a/utils/src/test/java/com/cloud/utils/testcase/NioTest.java
+++ b/utils/src/test/java/com/cloud/utils/testcase/NioTest.java
@@ -98,7 +98,7 @@ public void setUp() {
testBytes = new byte[1000000];
randomGenerator.nextBytes(testBytes);
- server = new NioServer("NioTestServer", 0, 1, new NioTestServer());
+ server = new NioServer("NioTestServer", 0, 1, new NioTestServer(), null);
try {
server.start();
} catch (final NioConnectionException e) {
diff --git a/utils/src/test/java/org/apache/cloudstack/utils/hypervisor/HypervisorUtilsTest.java b/utils/src/test/java/org/apache/cloudstack/utils/hypervisor/HypervisorUtilsTest.java
index f68776760d2..62969c8403c 100644
--- a/utils/src/test/java/org/apache/cloudstack/utils/hypervisor/HypervisorUtilsTest.java
+++ b/utils/src/test/java/org/apache/cloudstack/utils/hypervisor/HypervisorUtilsTest.java
@@ -58,7 +58,7 @@ public void checkVolumeFileForActivityTest() throws IOException {
System.out.print("Testing block on modified files - ");
String filePath = "./testfileinactive";
int timeoutSeconds = 8;
- long thresholdMilliseconds = 2000;
+ long thresholdMilliseconds = 1000;
File file = new File(filePath);
long startTime = setupcheckVolumeFileForActivityFile(file, _minFileSize);
diff --git a/utils/src/test/java/org/apache/cloudstack/utils/security/CertUtilsTest.java b/utils/src/test/java/org/apache/cloudstack/utils/security/CertUtilsTest.java
new file mode 100644
index 00000000000..1fed1765601
--- /dev/null
+++ b/utils/src/test/java/org/apache/cloudstack/utils/security/CertUtilsTest.java
@@ -0,0 +1,118 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.utils.security;
+
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.RSAPublicKey;
+import java.util.Arrays;
+import java.util.List;
+
+import org.bouncycastle.asn1.x509.GeneralName;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class CertUtilsTest {
+ KeyPair caKeyPair;
+ X509Certificate caCertificate;
+
+ @Before
+ public void setUp() throws Exception {
+ caKeyPair = CertUtils.generateRandomKeyPair(1024);
+ caCertificate = CertUtils.generateV3Certificate(null, caKeyPair, caKeyPair.getPublic(), "CN=test", "SHA256WithRSAEncryption", 365, null, null);
+ }
+
+ @Test
+ public void testGenerateRandomKeyPair() throws Exception {
+ final int size = 2048;
+ final KeyPair kp = CertUtils.generateRandomKeyPair(size);
+ Assert.assertEquals(((RSAPublicKey)kp.getPublic()).getModulus().bitLength(), size);
+ }
+
+ @Test
+ public void testCertificateConversionMethods() throws Exception {
+ final X509Certificate in = caCertificate;
+ final String pem = CertUtils.x509CertificateToPem(in);
+ final X509Certificate out = CertUtils.pemToX509Certificate(pem);
+ Assert.assertTrue(pem.startsWith("-----BEGIN CERTIFICATE-----\n"));
+ Assert.assertTrue(pem.endsWith("-----END CERTIFICATE-----\n"));
+ Assert.assertEquals(in.getSerialNumber(), out.getSerialNumber());
+ Assert.assertArrayEquals(in.getSignature(), out.getSignature());
+ Assert.assertEquals(in.getSigAlgName(), out.getSigAlgName());
+ Assert.assertEquals(in.getPublicKey(), out.getPublicKey());
+ Assert.assertEquals(in.getNotBefore(), out.getNotBefore());
+ Assert.assertEquals(in.getNotAfter(), out.getNotAfter());
+ Assert.assertEquals(in.getIssuerDN().toString(), out.getIssuerDN().toString());
+ }
+
+ @Test
+ public void testKeysConversionMethods() throws Exception {
+ final KeyPair kp = CertUtils.generateRandomKeyPair(2048);
+
+ final PrivateKey inPrivateKey = kp.getPrivate();
+ final PrivateKey outPrivateKey = CertUtils.pemToPrivateKey(CertUtils.privateKeyToPem(inPrivateKey));
+ Assert.assertEquals(inPrivateKey.getAlgorithm(), outPrivateKey.getAlgorithm());
+ Assert.assertEquals(inPrivateKey.getFormat(), outPrivateKey.getFormat());
+ Assert.assertArrayEquals(inPrivateKey.getEncoded(), outPrivateKey.getEncoded());
+
+ final PublicKey inPublicKey = kp.getPublic();
+ final PublicKey outPublicKey = CertUtils.pemToPublicKey(CertUtils.publicKeyToPem(inPublicKey));
+ Assert.assertEquals(inPublicKey.getAlgorithm(), outPublicKey.getAlgorithm());
+ Assert.assertEquals(inPublicKey.getFormat(), inPublicKey.getFormat());
+ Assert.assertArrayEquals(inPublicKey.getEncoded(), outPublicKey.getEncoded());
+ }
+
+ @Test
+ public void testGenerateRandomBigInt() throws Exception {
+ Assert.assertNotEquals(CertUtils.generateRandomBigInt(), CertUtils.generateRandomBigInt());
+ }
+
+ @Test
+ public void testGenerateCertificate() throws Exception {
+ final KeyPair clientKeyPair = CertUtils.generateRandomKeyPair(1024);
+ final List<String> domainNames = Arrays.asList("domain1.com", "www.2.domain2.com", "3.domain3.com");
+ final List<String> addressList = Arrays.asList("1.2.3.4", "192.168.1.1", "2a02:120b:2c16:f6d0:d9df:8ebc:e44a:f181");
+
+ final X509Certificate clientCert = CertUtils.generateV3Certificate(caCertificate, caKeyPair, clientKeyPair.getPublic(),
+ "CN=domain.example", "SHA256WithRSAEncryption", 10, domainNames, addressList);
+
+ clientCert.verify(caKeyPair.getPublic());
+ Assert.assertEquals(clientCert.getIssuerDN(), caCertificate.getIssuerDN());
+ Assert.assertEquals(clientCert.getSigAlgName(), "SHA256WITHRSA");
+ Assert.assertArrayEquals(clientCert.getPublicKey().getEncoded(), clientKeyPair.getPublic().getEncoded());
+ Assert.assertNotNull(clientCert.getSubjectAlternativeNames());
+
+ for (final List<?> altNames : clientCert.getSubjectAlternativeNames()) {
+ Assert.assertTrue(altNames.size() == 2);
+ final Object first = altNames.get(0);
+ final Object second = altNames.get(1);
+ if (first instanceof Integer && ((Integer) first) == GeneralName.iPAddress) {
+ Assert.assertTrue(addressList.contains((String) second));
+ }
+ if (first instanceof Integer && ((Integer) first) == GeneralName.dNSName) {
+ Assert.assertTrue(domainNames.contains((String) second));
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/utils/src/test/java/org/apache/cloudstack/utils/security/DigestHelperTest.java b/utils/src/test/java/org/apache/cloudstack/utils/security/DigestHelperTest.java
new file mode 100644
index 00000000000..45408827376
--- /dev/null
+++ b/utils/src/test/java/org/apache/cloudstack/utils/security/DigestHelperTest.java
@@ -0,0 +1,102 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.utils.security;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+
+import com.amazonaws.util.StringInputStream;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class DigestHelperTest {
+
+ private final static String INPUT_STRING = "01234567890123456789012345678901234567890123456789012345678901234567890123456789\n";
+ private final static String INPUT_STRING_NO2 = "01234567890123456789012345678901234567890123456789012345678901234567890123456789b\n";
+ private final static String INPUT_STRING_NO3 = "01234567890123456789012345678901234567890123456789012345678901234567890123456789h\n";
+ private final static String SHA256_CHECKSUM = "{SHA-256}c6ab15af7842d23d3c06c138b53a7d09c5e351a79c4eb3c8ca8d65e5ce8900ab";
+ private final static String SHA1_CHECKSUM = "{SHA-1}49e4b2f4292b63e88597c127d11bc2cc0f2ca0ff";
+ private final static String MD5_CHECKSUM = "{MD5}d141a8eeaf6bba779d1d1dc5102a81c5";
+ private final static String ZERO_PADDED_MD5_CHECKSUM = "{MD5}0e51dfa74b87f19dd5e0124d6a2195e3";
+ private final static String ZERO_PADDED_SHA256_CHECKSUM = "{SHA-256}08b5ae0c7d7d45d8ed406d7c3c7da695b81187903694314d97f8a37752a6b241";
+ private static final String MD5 = "MD5";
+ private static final String SHA_256 = "SHA-256";
+ private static InputStream inputStream;
+ private InputStream inputStream2;
+
+
+ @Test
+ public void check_SHA256() throws Exception {
+ Assert.assertTrue(DigestHelper.check(SHA256_CHECKSUM, inputStream));
+ }
+
+ @Test
+ public void check_SHA1() throws Exception {
+ Assert.assertTrue(DigestHelper.check(SHA1_CHECKSUM, inputStream));
+ }
+
+ @Test
+ public void check_MD5() throws Exception {
+ Assert.assertTrue(DigestHelper.check(MD5_CHECKSUM, inputStream));
+ }
+
+ @Test
+ public void testDigestSHA256() throws Exception {
+ String result = DigestHelper.digest(SHA_256, inputStream).toString();
+ Assert.assertEquals(SHA256_CHECKSUM, result);
+ }
+
+ @Test
+ public void testDigestSHA1() throws Exception {
+ String result = DigestHelper.digest("SHA-1", inputStream).toString();
+ Assert.assertEquals(SHA1_CHECKSUM, result);
+ }
+
+ @Test
+ public void testDigestMD5() throws Exception {
+ String result = DigestHelper.digest(MD5, inputStream).toString();
+ Assert.assertEquals(MD5_CHECKSUM, result);
+ }
+
+ @Test
+ public void testZeroPaddedDigestMD5() throws Exception {
+ inputStream2 = new StringInputStream(INPUT_STRING_NO2);
+ String result = DigestHelper.digest(MD5, inputStream2).toString();
+ Assert.assertEquals(ZERO_PADDED_MD5_CHECKSUM, result);
+ }
+
+ @Test
+ public void testZeroPaddedDigestSHA256() throws Exception {
+ inputStream2 = new StringInputStream(INPUT_STRING_NO3);
+ String result = DigestHelper.digest(SHA_256, inputStream2).toString();
+ Assert.assertEquals(ZERO_PADDED_SHA256_CHECKSUM, result);
+ }
+
+ @BeforeClass
+ public static void init() throws UnsupportedEncodingException {
+ inputStream = new StringInputStream(INPUT_STRING);
+ }
+ @Before
+ public void reset() throws IOException {
+ inputStream.reset();
+ }
+}
+
+//Generated with love by TestMe :) Please report issues and submit feature requests at: http://weirddev.com/forum#!/testme
\ No newline at end of file
diff --git a/vmware-base/pom.xml b/vmware-base/pom.xml
index 7579599e0ee..01cfb3a52f1 100644
--- a/vmware-base/pom.xml
+++ b/vmware-base/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
- <version>4.10.1.0-SNAPSHOT</version>
+ <version>4.11.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
@@ -42,6 +42,11 @@
<artifactId>cloud-api</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-engine-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/DatastoreMO.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/DatastoreMO.java
index 290e1a0bdb6..1152ba5078a 100644
--- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/DatastoreMO.java
+++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/DatastoreMO.java
@@ -166,6 +166,10 @@ public boolean deleteFolder(String folder, ManagedObjectReference morDc) throws
}
public boolean deleteFile(String path, ManagedObjectReference morDc, boolean testExistence) throws Exception {
+ return deleteFile(path, morDc, testExistence, null);
+ }
+
+ public boolean deleteFile(String path, ManagedObjectReference morDc, boolean testExistence, String excludeFolders) throws Exception {
String datastoreName = getName();
ManagedObjectReference morFileManager = _context.getServiceContent().getFileManager();
@@ -180,7 +184,7 @@ public boolean deleteFile(String path, ManagedObjectReference morDc, boolean tes
try {
if (testExistence && !fileExists(fullPath)) {
- String searchResult = searchFileInSubFolders(file.getFileName(), true);
+ String searchResult = searchFileInSubFolders(file.getFileName(), true, excludeFolders);
if (searchResult == null) {
return true;
} else {
@@ -352,8 +356,13 @@ public boolean folderExists(String folderParentDatastorePath, String folderName)
}
public String searchFileInSubFolders(String fileName, boolean caseInsensitive) throws Exception {
+ return searchFileInSubFolders(fileName,caseInsensitive,null);
+ }
+
+ public String searchFileInSubFolders(String fileName, boolean caseInsensitive, String excludeFolders) throws Exception {
String datastorePath = "[" + getName() + "]";
String rootDirectoryFilePath = String.format("%s %s", datastorePath, fileName);
+ String[] searchExcludedFolders = getSearchExcludedFolders(excludeFolders);
if (fileExists(rootDirectoryFilePath)) {
return rootDirectoryFilePath;
}
@@ -380,6 +389,9 @@ public String searchFileInSubFolders(String fileName, boolean caseInsensitive) t
if (parentFolderPath.endsWith("]"))
absoluteFileName += " ";
absoluteFileName += fi.getPath();
+ if(isValidCloudStackFolderPath(parentFolderPath, searchExcludedFolders)) {
+ return absoluteFileName;
+ }
break;
}
}
@@ -387,6 +399,20 @@ public String searchFileInSubFolders(String fileName, boolean caseInsensitive) t
return absoluteFileName;
}
+ private String[] getSearchExcludedFolders(String excludeFolders) {
+ return excludeFolders != null ? excludeFolders.replaceAll("\\s","").split(",") : new String[] {};
+ }
+
+ private boolean isValidCloudStackFolderPath(String dataStoreFolderPath, String[] searchExcludedFolders) throws Exception {
+ String dsFolder = dataStoreFolderPath.replaceFirst("\\[" + getName() + "\\]", "").trim();
+ for( String excludedFolder : searchExcludedFolders) {
+ if (dsFolder.startsWith(excludedFolder)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
public boolean isAccessibleToHost(String hostValue) throws Exception {
boolean isAccessible = true;
List<DatastoreHostMount> hostMounts = getHostMounts();
diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java
index ef3f0ae327c..bece91a98f5 100644
--- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java
+++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java
@@ -16,11 +16,45 @@
// under the License.
package com.cloud.hypervisor.vmware.mo;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.InvalidParameterException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.traversal.DocumentTraversal;
+import org.w3c.dom.traversal.NodeFilter;
+import org.w3c.dom.traversal.NodeIterator;
+import org.xml.sax.SAXException;
+
import com.cloud.exception.CloudException;
import com.cloud.hypervisor.vmware.util.VmwareContext;
import com.cloud.hypervisor.vmware.util.VmwareHelper;
import com.cloud.network.Networks.BroadcastDomainType;
+import com.cloud.offering.NetworkOffering;
import com.cloud.utils.ActionDelegate;
+import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.cisco.n1kv.vsm.NetconfHelper;
import com.cloud.utils.cisco.n1kv.vsm.PolicyMap;
@@ -54,6 +88,7 @@
import com.vmware.vim25.LongPolicy;
import com.vmware.vim25.ManagedObjectReference;
import com.vmware.vim25.MethodFault;
+import com.vmware.vim25.NumericRange;
import com.vmware.vim25.ObjectContent;
import com.vmware.vim25.OvfCreateImportSpecParams;
import com.vmware.vim25.OvfCreateImportSpecResult;
@@ -79,35 +114,9 @@
import com.vmware.vim25.VirtualSCSIController;
import com.vmware.vim25.VirtualSCSISharing;
import com.vmware.vim25.VmwareDistributedVirtualSwitchPvlanSpec;
+import com.vmware.vim25.VmwareDistributedVirtualSwitchTrunkVlanSpec;
import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanIdSpec;
import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanSpec;
-import org.apache.log4j.Logger;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.traversal.DocumentTraversal;
-import org.w3c.dom.traversal.NodeFilter;
-import org.w3c.dom.traversal.NodeIterator;
-import org.xml.sax.SAXException;
-
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.security.InvalidParameterException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
public class HypervisorHostHelper {
private static final Logger s_logger = Logger.getLogger(HypervisorHostHelper.class);
@@ -452,13 +461,14 @@ public static void updatePortProfile(VmwareContext context, String ethPortProfil
* @param timeOutMs
* @param vSwitchType
* @param numPorts
+ * @param details
* @return
* @throws Exception
*/
public static Pair<ManagedObjectReference, String> prepareNetwork(String physicalNetwork, String namePrefix, HostMO hostMo, String vlanId, String secondaryvlanId,
- Integer networkRateMbps, Integer networkRateMulticastMbps, long timeOutMs, VirtualSwitchType vSwitchType, int numPorts, String gateway,
- boolean configureVServiceInNexus, BroadcastDomainType broadcastDomainType, Map<String, String> vsmCredentials) throws Exception {
+ Integer networkRateMbps, Integer networkRateMulticastMbps, long timeOutMs, VirtualSwitchType vSwitchType, int numPorts, String gateway,
+ boolean configureVServiceInNexus, BroadcastDomainType broadcastDomainType, Map<String, String> vsmCredentials, Map<NetworkOffering.Detail, String> details) throws Exception {
ManagedObjectReference morNetwork = null;
VmwareContext context = hostMo.getContext();
ManagedObjectReference dcMor = hostMo.getHyperHostDatacenter();
@@ -501,12 +511,18 @@ public static void updatePortProfile(VmwareContext context, String ethPortProfil
// No doubt about this, depending on vid=null to avoid lots of code below
vid = null;
} else {
+ if (vlanId != null) {
+ vlanId = vlanId.replace("vlan://", "");
+ }
networkName = composeCloudNetworkName(namePrefix, vlanId, secondaryvlanId, networkRateMbps, physicalNetwork);
- if (vlanId != null && !UNTAGGED_VLAN_NAME.equalsIgnoreCase(vlanId)) {
+ if (vlanId != null && !UNTAGGED_VLAN_NAME.equalsIgnoreCase(vlanId) && !StringUtils.containsAny(vlanId, ",-")) {
createGCTag = true;
vid = Integer.parseInt(vlanId);
}
+ if (vlanId != null && StringUtils.containsAny(vlanId, ",-")) {
+ createGCTag = true;
+ }
if (secondaryvlanId != null) {
spvlanid = Integer.parseInt(secondaryvlanId);
}
@@ -544,7 +560,7 @@ public static void updatePortProfile(VmwareContext context, String ethPortProfil
dvSwitchMo = new DistributedVirtualSwitchMO(context, morDvSwitch);
shapingPolicy = getDVSShapingPolicy(networkRateMbps);
- secPolicy = createDVSSecurityPolicy();
+ secPolicy = createDVSSecurityPolicy(details);
// First, if both vlan id and pvlan id are provided, we need to
// reconfigure the DVSwitch to have a tuple <vlan id, pvlan id> of
@@ -562,7 +578,7 @@ public static void updatePortProfile(VmwareContext context, String ethPortProfil
portGroupPolicy.setPortConfigResetAtDisconnect(true);
}
// Next, create the port group. For this, we need to create a VLAN spec.
- createPortGroup(physicalNetwork, networkName, vid, spvlanid, dataCenterMo, shapingPolicy, secPolicy, portGroupPolicy, dvSwitchMo, numPorts, autoExpandSupported);
+ createPortGroup(physicalNetwork, networkName, vlanId, vid, spvlanid, dataCenterMo, shapingPolicy, secPolicy, portGroupPolicy, dvSwitchMo, numPorts, autoExpandSupported);
bWaitPortGroupReady = true;
}
} else if (vSwitchType == VirtualSwitchType.NexusDistributedVirtualSwitch) {
@@ -699,8 +715,8 @@ private static void setupPVlanPair(DistributedVirtualSwitchMO dvSwitchMo, Manage
}
- private static void createPortGroup(String physicalNetwork, String networkName, Integer vid, Integer spvlanid, DatacenterMO dataCenterMo,
- DVSTrafficShapingPolicy shapingPolicy, DVSSecurityPolicy secPolicy, VMwareDVSPortgroupPolicy portGroupPolicy, DistributedVirtualSwitchMO dvSwitchMo, int numPorts, boolean autoExpandSupported)
+ private static void createPortGroup(String physicalNetwork, String networkName, String vlanRange, Integer vid, Integer spvlanid, DatacenterMO dataCenterMo,
+ DVSTrafficShapingPolicy shapingPolicy, DVSSecurityPolicy secPolicy, VMwareDVSPortgroupPolicy portGroupPolicy, DistributedVirtualSwitchMO dvSwitchMo, int numPorts, boolean autoExpandSupported)
throws Exception {
VmwareDistributedVirtualSwitchVlanSpec vlanSpec = null;
VmwareDistributedVirtualSwitchPvlanSpec pvlanSpec = null;
@@ -710,7 +726,7 @@ private static void createPortGroup(String physicalNetwork, String networkName,
// Next, create the port group. For this, we need to create a VLAN spec.
// NOTE - VmwareDistributedVirtualSwitchPvlanSpec extends VmwareDistributedVirtualSwitchVlanSpec.
if (vid == null || spvlanid == null) {
- vlanSpec = createDVPortVlanIdSpec(vid);
+ vlanSpec = createDVPortVlanSpec(vid, vlanRange);
dvsPortSetting = createVmwareDVPortSettingSpec(shapingPolicy, secPolicy, vlanSpec);
} else if (spvlanid != null) {
// Create a pvlan spec. The pvlan spec is different from the pvlan config spec
@@ -851,12 +867,57 @@ public static boolean isSpecMatch(DVPortgroupConfigInfo currentDvPortgroupInfo,
}
}
- VmwareDistributedVirtualSwitchVlanIdSpec oldVlanSpec = (VmwareDistributedVirtualSwitchVlanIdSpec)((
- VMwareDVSPortSetting)currentDvPortgroupInfo.getDefaultPortConfig()).getVlan();
- VmwareDistributedVirtualSwitchVlanIdSpec newVlanSpec = (VmwareDistributedVirtualSwitchVlanIdSpec)((
- VMwareDVSPortSetting)newDvPortGroupSpec.getDefaultPortConfig()).getVlan();
- int oldVlanId = oldVlanSpec.getVlanId();
- int newVlanId = newVlanSpec.getVlanId();
+ VMwareDVSPortSetting currentPortSetting = ((VMwareDVSPortSetting)currentDvPortgroupInfo.getDefaultPortConfig());
+ VMwareDVSPortSetting newPortSetting = ((VMwareDVSPortSetting)newDvPortGroupSpec.getDefaultPortConfig());
+ if ((currentPortSetting.getSecurityPolicy() == null && newPortSetting.getSecurityPolicy() != null) ||
+ (currentPortSetting.getSecurityPolicy() != null && newPortSetting.getSecurityPolicy() == null)) {
+ specMatches = false;
+ }
+ if (currentPortSetting.getSecurityPolicy() != null && newPortSetting.getSecurityPolicy() != null) {
+ if (currentPortSetting.getSecurityPolicy().getAllowPromiscuous() != null &&
+ newPortSetting.getSecurityPolicy().getAllowPromiscuous() != null &&
+ newPortSetting.getSecurityPolicy().getAllowPromiscuous().isValue() != null &&
+ !newPortSetting.getSecurityPolicy().getAllowPromiscuous().isValue().equals(currentPortSetting.getSecurityPolicy().getAllowPromiscuous().isValue())) {
+ specMatches = false;
+ }
+ if (currentPortSetting.getSecurityPolicy().getForgedTransmits() != null &&
+ newPortSetting.getSecurityPolicy().getForgedTransmits() != null &&
+ newPortSetting.getSecurityPolicy().getForgedTransmits().isValue() != null &&
+ !newPortSetting.getSecurityPolicy().getForgedTransmits().isValue().equals(currentPortSetting.getSecurityPolicy().getForgedTransmits().isValue())) {
+ specMatches = false;
+ }
+ if (currentPortSetting.getSecurityPolicy().getMacChanges() != null &&
+ newPortSetting.getSecurityPolicy().getMacChanges() != null &&
+ newPortSetting.getSecurityPolicy().getMacChanges().isValue() != null &&
+ !newPortSetting.getSecurityPolicy().getMacChanges().isValue().equals(currentPortSetting.getSecurityPolicy().getMacChanges().isValue())) {
+ specMatches = false;
+ }
+ }
+
+ VmwareDistributedVirtualSwitchVlanSpec oldVlanSpec = currentPortSetting.getVlan();
+ VmwareDistributedVirtualSwitchVlanSpec newVlanSpec = newPortSetting.getVlan();
+
+ int oldVlanId, newVlanId;
+ if (oldVlanSpec instanceof VmwareDistributedVirtualSwitchPvlanSpec && newVlanSpec instanceof VmwareDistributedVirtualSwitchPvlanSpec) {
+ VmwareDistributedVirtualSwitchPvlanSpec oldpVlanSpec = (VmwareDistributedVirtualSwitchPvlanSpec) oldVlanSpec;
+ VmwareDistributedVirtualSwitchPvlanSpec newpVlanSpec = (VmwareDistributedVirtualSwitchPvlanSpec) newVlanSpec;
+ oldVlanId = oldpVlanSpec.getPvlanId();
+ newVlanId = newpVlanSpec.getPvlanId();
+ } else if (oldVlanSpec instanceof VmwareDistributedVirtualSwitchTrunkVlanSpec && newVlanSpec instanceof VmwareDistributedVirtualSwitchTrunkVlanSpec) {
+ VmwareDistributedVirtualSwitchTrunkVlanSpec oldpVlanSpec = (VmwareDistributedVirtualSwitchTrunkVlanSpec) oldVlanSpec;
+ VmwareDistributedVirtualSwitchTrunkVlanSpec newpVlanSpec = (VmwareDistributedVirtualSwitchTrunkVlanSpec) newVlanSpec;
+ oldVlanId = oldpVlanSpec.getVlanId().get(0).getStart();
+ newVlanId = newpVlanSpec.getVlanId().get(0).getStart();
+ } else if (oldVlanSpec instanceof VmwareDistributedVirtualSwitchVlanIdSpec && newVlanSpec instanceof VmwareDistributedVirtualSwitchVlanIdSpec) {
+ VmwareDistributedVirtualSwitchVlanIdSpec oldVlanIdSpec = (VmwareDistributedVirtualSwitchVlanIdSpec) oldVlanSpec;
+ VmwareDistributedVirtualSwitchVlanIdSpec newVlanIdSpec = (VmwareDistributedVirtualSwitchVlanIdSpec) newVlanSpec;
+ oldVlanId = oldVlanIdSpec.getVlanId();
+ newVlanId = newVlanIdSpec.getVlanId();
+ } else {
+ s_logger.debug("Old and new vlan spec type mismatch found for [" + dvPortGroupName + "] has changed. Old spec type is: " + oldVlanSpec.getClass() + ", and new spec type is:" + newVlanSpec.getClass());
+ return false;
+ }
+
if (oldVlanId != newVlanId) {
s_logger.info("Detected that new VLAN [" + newVlanId + "] of dvPortGroup [" + dvPortGroupName +
"] is different from current VLAN [" + oldVlanId + "]");
@@ -994,25 +1055,114 @@ public static VMwareDVSPvlanConfigSpec createDVPortPvlanConfigSpec(int vlanId, i
return pvlanConfigSpec;
}
- public static VmwareDistributedVirtualSwitchVlanIdSpec createDVPortVlanIdSpec(Integer vlanId) {
+ public static VmwareDistributedVirtualSwitchVlanSpec createDVPortVlanSpec(Integer vlanId, String vlanRange) {
+ if (vlanId == null && vlanRange != null && !vlanRange.isEmpty()) {
+ s_logger.debug("Creating dvSwitch port vlan-trunk spec with range: " + vlanRange);
+ VmwareDistributedVirtualSwitchTrunkVlanSpec trunkVlanSpec = new VmwareDistributedVirtualSwitchTrunkVlanSpec();
+ for (final String vlanRangePart : vlanRange.split(",")) {
+ if (vlanRangePart == null || vlanRange.isEmpty()) {
+ continue;
+ }
+ final NumericRange numericRange = new NumericRange();
+ if (vlanRangePart.contains("-")) {
+ final String[] range = vlanRangePart.split("-");
+ if (range.length == 2 && range[0] != null && range[1] != null) {
+ numericRange.setStart(NumbersUtil.parseInt(range[0], 0));
+ numericRange.setEnd(NumbersUtil.parseInt(range[1], 0));
+ } else {
+ continue;
+ }
+ } else {
+ numericRange.setStart(NumbersUtil.parseInt(vlanRangePart, 0));
+ numericRange.setEnd(NumbersUtil.parseInt(vlanRangePart, 0));
+ }
+ trunkVlanSpec.getVlanId().add(numericRange);
+ }
+ if (trunkVlanSpec.getVlanId().size() != 0) {
+ return trunkVlanSpec;
+ }
+ }
VmwareDistributedVirtualSwitchVlanIdSpec vlanIdSpec = new VmwareDistributedVirtualSwitchVlanIdSpec();
- vlanIdSpec.setVlanId(vlanId == null ? 0 : vlanId.intValue());
+ vlanIdSpec.setVlanId(vlanId == null ? 0 : vlanId);
+ s_logger.debug("Creating dvSwitch port vlan-id spec with id: " + vlanIdSpec.getVlanId());
return vlanIdSpec;
}
- public static DVSSecurityPolicy createDVSSecurityPolicy() {
+ public static Map<NetworkOffering.Detail, String> getDefaultSecurityDetails() {
+ final Map<NetworkOffering.Detail, String> details = new HashMap<>();
+ details.put(NetworkOffering.Detail.PromiscuousMode, NetworkOrchestrationService.PromiscuousMode.value().toString());
+ details.put(NetworkOffering.Detail.MacAddressChanges, NetworkOrchestrationService.MacAddressChanges.value().toString());
+ details.put(NetworkOffering.Detail.ForgedTransmits, NetworkOrchestrationService.ForgedTransmits.value().toString());
+ return details;
+ }
+
+ public static DVSSecurityPolicy createDVSSecurityPolicy(Map<NetworkOffering.Detail, String> nicDetails) {
DVSSecurityPolicy secPolicy = new DVSSecurityPolicy();
BoolPolicy allow = new BoolPolicy();
allow.setValue(true);
+ BoolPolicy deny = new BoolPolicy();
+ deny.setValue(false);
+ secPolicy.setAllowPromiscuous(deny);
secPolicy.setForgedTransmits(allow);
- secPolicy.setAllowPromiscuous(allow);
secPolicy.setMacChanges(allow);
+
+ if (nicDetails == null) {
+ nicDetails = getDefaultSecurityDetails();
+ }
+
+ if (nicDetails.containsKey(NetworkOffering.Detail.PromiscuousMode)) {
+ if (Boolean.valueOf(nicDetails.get(NetworkOffering.Detail.PromiscuousMode))) {
+ secPolicy.setAllowPromiscuous(allow);
+ } else {
+ secPolicy.setAllowPromiscuous(deny);
+ }
+ }
+ if (nicDetails.containsKey(NetworkOffering.Detail.ForgedTransmits)) {
+ if (Boolean.valueOf(nicDetails.get(NetworkOffering.Detail.ForgedTransmits))) {
+ secPolicy.setForgedTransmits(allow);
+ } else {
+ secPolicy.setForgedTransmits(deny);
+ }
+ }
+ if (nicDetails.containsKey(NetworkOffering.Detail.MacAddressChanges)) {
+ if (Boolean.valueOf(nicDetails.get(NetworkOffering.Detail.MacAddressChanges))) {
+ secPolicy.setMacChanges(allow);
+ } else {
+ secPolicy.setMacChanges(deny);
+ }
+ }
+
+ return secPolicy;
+ }
+
+ public static HostNetworkSecurityPolicy createVSSecurityPolicy(Map<NetworkOffering.Detail, String> nicDetails) {
+ HostNetworkSecurityPolicy secPolicy = new HostNetworkSecurityPolicy();
+ secPolicy.setAllowPromiscuous(Boolean.FALSE);
+ secPolicy.setForgedTransmits(Boolean.TRUE);
+ secPolicy.setMacChanges(Boolean.TRUE);
+
+ if (nicDetails == null) {
+ nicDetails = getDefaultSecurityDetails();
+ }
+
+ if (nicDetails.containsKey(NetworkOffering.Detail.PromiscuousMode)) {
+ secPolicy.setAllowPromiscuous(Boolean.valueOf(nicDetails.get(NetworkOffering.Detail.PromiscuousMode)));
+ }
+
+ if (nicDetails.containsKey(NetworkOffering.Detail.ForgedTransmits)) {
+ secPolicy.setForgedTransmits(Boolean.valueOf(nicDetails.get(NetworkOffering.Detail.ForgedTransmits)));
+ }
+
+ if (nicDetails.containsKey(NetworkOffering.Detail.MacAddressChanges)) {
+ secPolicy.setMacChanges(Boolean.valueOf(nicDetails.get(NetworkOffering.Detail.MacAddressChanges)));
+ }
+
return secPolicy;
}
public static Pair<ManagedObjectReference, String> prepareNetwork(String vSwitchName, String namePrefix, HostMO hostMo, String vlanId, Integer networkRateMbps,
- Integer networkRateMulticastMbps, long timeOutMs, boolean syncPeerHosts, BroadcastDomainType broadcastDomainType, String nicUuid) throws Exception {
+ Integer networkRateMulticastMbps, long timeOutMs, boolean syncPeerHosts, BroadcastDomainType broadcastDomainType, String nicUuid, Map<NetworkOffering.Detail, String> nicDetails) throws Exception {
HostVirtualSwitch vSwitch;
if (vSwitchName == null) {
@@ -1059,13 +1209,8 @@ public static DVSSecurityPolicy createDVSSecurityPolicy() {
}
}
- HostNetworkSecurityPolicy secPolicy = null;
- if (namePrefix.equalsIgnoreCase("cloud.private")) {
- secPolicy = new HostNetworkSecurityPolicy();
- secPolicy.setAllowPromiscuous(Boolean.TRUE);
- secPolicy.setForgedTransmits(Boolean.TRUE);
- secPolicy.setMacChanges(Boolean.TRUE);
- }
+ HostNetworkSecurityPolicy secPolicy = createVSSecurityPolicy(nicDetails);
+
HostNetworkTrafficShapingPolicy shapingPolicy = null;
if (networkRateMbps != null && networkRateMbps.intValue() > 0) {
shapingPolicy = new HostNetworkTrafficShapingPolicy();
@@ -1105,7 +1250,7 @@ public static DVSSecurityPolicy createDVSSecurityPolicy() {
bWaitPortGroupReady = false;
} else {
HostPortGroupSpec spec = hostMo.getPortGroupSpec(networkName);
- if (!isSpecMatch(spec, vid, shapingPolicy)) {
+ if (!isSpecMatch(spec, vid, secPolicy, shapingPolicy)) {
hostMo.updatePortGroup(vSwitch, networkName, vid, secPolicy, shapingPolicy);
bWaitPortGroupReady = true;
}
@@ -1149,7 +1294,7 @@ public static DVSSecurityPolicy createDVSSecurityPolicy() {
if (s_logger.isDebugEnabled())
s_logger.debug("Prepare network on other host, vlan: " + vlanId + ", host: " + otherHostMo.getHostName());
prepareNetwork(vSwitchName, namePrefix, otherHostMo, vlanId, networkRateMbps, networkRateMulticastMbps, timeOutMs, false,
- broadcastDomainType, nicUuid);
+ broadcastDomainType, nicUuid, nicDetails);
} catch (Exception e) {
s_logger.warn("Unable to prepare network on other host, vlan: " + vlanId + ", host: " + otherHostMo.getHostName());
}
@@ -1172,7 +1317,7 @@ public static DVSSecurityPolicy createDVSSecurityPolicy() {
return new Pair<ManagedObjectReference, String>(morNetwork, networkName);
}
- private static boolean isSpecMatch(HostPortGroupSpec spec, Integer vlanId, HostNetworkTrafficShapingPolicy shapingPolicy) {
+ private static boolean isSpecMatch(HostPortGroupSpec spec, Integer vlanId, HostNetworkSecurityPolicy securityPolicy, HostNetworkTrafficShapingPolicy shapingPolicy) {
// check VLAN configuration
if (vlanId != null) {
if (vlanId.intValue() != spec.getVlanId())
@@ -1182,16 +1327,36 @@ private static boolean isSpecMatch(HostPortGroupSpec spec, Integer vlanId, HostN
return false;
}
+ // check security policy for the portgroup
+ HostNetworkSecurityPolicy secPolicyInSpec = null;
+ if (spec.getPolicy() != null) {
+ secPolicyInSpec = spec.getPolicy().getSecurity();
+ }
+
+ if ((secPolicyInSpec != null && securityPolicy == null) || (secPolicyInSpec == null && securityPolicy != null)) {
+ return false;
+ }
+
+ if (secPolicyInSpec != null && securityPolicy != null
+ && ((securityPolicy.isAllowPromiscuous() != null && !securityPolicy.isAllowPromiscuous().equals(secPolicyInSpec.isAllowPromiscuous()))
+ || (securityPolicy.isForgedTransmits() != null && !securityPolicy.isForgedTransmits().equals(secPolicyInSpec.isForgedTransmits()))
+ || (securityPolicy.isMacChanges() != null && securityPolicy.isMacChanges().equals(secPolicyInSpec.isMacChanges())))) {
+ return false;
+ }
+
// check traffic shaping configuration
HostNetworkTrafficShapingPolicy policyInSpec = null;
- if (spec.getPolicy() != null)
+ if (spec.getPolicy() != null) {
policyInSpec = spec.getPolicy().getShapingPolicy();
+ }
- if (policyInSpec != null && shapingPolicy == null || policyInSpec == null && shapingPolicy != null)
+ if ((policyInSpec != null && shapingPolicy == null) || (policyInSpec == null && shapingPolicy != null)) {
return false;
+ }
- if (policyInSpec == null && shapingPolicy == null)
+ if (policyInSpec == null && shapingPolicy == null) {
return true;
+ }
// so far policyInSpec and shapingPolicy should both not be null
if (policyInSpec.isEnabled() == null || !policyInSpec.isEnabled().booleanValue())
diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
index 3cf3ad1744f..c7bdbcdf241 100644
--- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
+++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
@@ -2220,7 +2220,48 @@ public int getScsiDeviceControllerKeyNoException() throws Exception {
if(devices != null && devices.size() > 0) {
for(VirtualDevice device : devices) {
- if(device instanceof VirtualLsiLogicController) {
+ if(device instanceof VirtualSCSIController) {
+ return device.getKey();
+ }
+ }
+ }
+
+ return -1;
+ }
+
+ public void ensureLsiLogicDeviceControllers(int count, int availableBusNum) throws Exception {
+ int scsiControllerKey = getLsiLogicDeviceControllerKeyNoException();
+ if (scsiControllerKey < 0) {
+ VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
+
+ int busNum = availableBusNum;
+ while (busNum < count) {
+ VirtualLsiLogicController scsiController = new VirtualLsiLogicController();
+ scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
+ scsiController.setBusNumber(busNum);
+ scsiController.setKey(busNum - VmwareHelper.MAX_SCSI_CONTROLLER_COUNT);
+ VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
+ scsiControllerSpec.setDevice(scsiController);
+ scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
+
+ vmConfig.getDeviceChange().add(scsiControllerSpec);
+ busNum++;
+ }
+ if (configureVm(vmConfig)) {
+ throw new Exception("Unable to add Lsi Logic controllers to the VM " + getName());
+ } else {
+ s_logger.info("Successfully added " + count + " LsiLogic Parallel SCSI controllers.");
+ }
+ }
+ }
+
+ private int getLsiLogicDeviceControllerKeyNoException() throws Exception {
+ List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().
+ getDynamicProperty(_mor, "config.hardware.device");
+
+ if (devices != null && devices.size() > 0) {
+ for (VirtualDevice device : devices) {
+ if (device instanceof VirtualLsiLogicController) {
return device.getKey();
}
}
diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareHelper.java b/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareHelper.java
index 65dfe7bd713..dddab4de5ad 100644
--- a/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareHelper.java
+++ b/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareHelper.java
@@ -89,7 +89,7 @@ public static boolean isReservedScsiDeviceNumber(int deviceNumber) {
}
public static VirtualDevice prepareNicOpaque(VirtualMachineMO vmMo, VirtualEthernetCardType deviceType, String portGroupName,
- String macAddress, int deviceNumber, int contextNumber, boolean conntected, boolean connectOnStart) throws Exception {
+ String macAddress, int contextNumber, boolean connected, boolean connectOnStart) throws Exception {
assert(vmMo.getRunningHost().hasOpaqueNSXNetwork());
@@ -123,18 +123,17 @@ public static VirtualDevice prepareNicOpaque(VirtualMachineMO vmMo, VirtualEther
VirtualDeviceConnectInfo connectInfo = new VirtualDeviceConnectInfo();
connectInfo.setAllowGuestControl(true);
- connectInfo.setConnected(conntected);
+ connectInfo.setConnected(connected);
connectInfo.setStartConnected(connectOnStart);
nic.setAddressType("Manual");
nic.setConnectable(connectInfo);
nic.setMacAddress(macAddress);
- nic.setUnitNumber(deviceNumber);
nic.setKey(-contextNumber);
return nic;
}
public static VirtualDevice prepareNicDevice(VirtualMachineMO vmMo, ManagedObjectReference morNetwork, VirtualEthernetCardType deviceType, String portGroupName,
- String macAddress, int deviceNumber, int contextNumber, boolean conntected, boolean connectOnStart) throws Exception {
+ String macAddress, int contextNumber, boolean connected, boolean connectOnStart) throws Exception {
VirtualEthernetCard nic;
switch (deviceType) {
@@ -166,18 +165,17 @@ public static VirtualDevice prepareNicDevice(VirtualMachineMO vmMo, ManagedObjec
VirtualDeviceConnectInfo connectInfo = new VirtualDeviceConnectInfo();
connectInfo.setAllowGuestControl(true);
- connectInfo.setConnected(conntected);
+ connectInfo.setConnected(connected);
connectInfo.setStartConnected(connectOnStart);
nic.setAddressType("Manual");
nic.setConnectable(connectInfo);
nic.setMacAddress(macAddress);
- nic.setUnitNumber(deviceNumber);
nic.setKey(-contextNumber);
return nic;
}
public static VirtualDevice prepareDvNicDevice(VirtualMachineMO vmMo, ManagedObjectReference morNetwork, VirtualEthernetCardType deviceType, String dvPortGroupName,
- String dvSwitchUuid, String macAddress, int deviceNumber, int contextNumber, boolean conntected, boolean connectOnStart) throws Exception {
+ String dvSwitchUuid, String macAddress, int contextNumber, boolean connected, boolean connectOnStart) throws Exception {
VirtualEthernetCard nic;
switch (deviceType) {
@@ -210,16 +208,13 @@ public static VirtualDevice prepareDvNicDevice(VirtualMachineMO vmMo, ManagedObj
dvPortConnection.setPortgroupKey(morNetwork.getValue());
dvPortBacking.setPort(dvPortConnection);
nic.setBacking(dvPortBacking);
- nic.setKey(30);
connectInfo.setAllowGuestControl(true);
- connectInfo.setConnected(conntected);
+ connectInfo.setConnected(connected);
connectInfo.setStartConnected(connectOnStart);
nic.setAddressType("Manual");
nic.setConnectable(connectInfo);
nic.setMacAddress(macAddress);
-
- nic.setUnitNumber(deviceNumber);
nic.setKey(-contextNumber);
return nic;
}
diff --git a/vmware-base/test/com/cloud/hypervisor/vmware/mo/DatastoreMOTest.java b/vmware-base/test/com/cloud/hypervisor/vmware/mo/DatastoreMOTest.java
new file mode 100644
index 00000000000..394d199ce50
--- /dev/null
+++ b/vmware-base/test/com/cloud/hypervisor/vmware/mo/DatastoreMOTest.java
@@ -0,0 +1,114 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package com.cloud.hypervisor.vmware.mo;
+
+import com.cloud.hypervisor.vmware.util.VmwareClient;
+import com.cloud.hypervisor.vmware.util.VmwareContext;
+import com.vmware.vim25.FileInfo;
+import com.vmware.vim25.HostDatastoreBrowserSearchResults;
+import com.vmware.vim25.ManagedObjectReference;
+import com.vmware.vim25.VimPortType;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.util.ArrayList;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.when;
+
+/**
+ * Created by sudharma_jain on 6/13/17.
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(DatastoreMO.class)
+public class DatastoreMOTest {
+ @Mock
+ VmwareContext _context ;
+ @Mock
+ VmwareClient _client;
+ @Mock
+ ManagedObjectReference _mor;
+ @Mock
+ HostDatastoreBrowserMO browserMo;
+ @Mock
+ VimPortType vimPortType;
+
+ DatastoreMO datastoreMO ;
+ String fileName = "ROOT-5.vmdk";
+
+
+ @Before
+ public void setUp() throws Exception {
+
+ datastoreMO = new DatastoreMO(_context, _mor);
+ PowerMockito.whenNew(HostDatastoreBrowserMO.class).withAnyArguments().thenReturn(browserMo);
+ when(_context.getVimClient()).thenReturn(_client);
+ when(_client.getDynamicProperty(any(ManagedObjectReference.class), eq("name"))).thenReturn("252d36c96cfb32f48ce7756ccb79ae37");
+
+ ArrayList<HostDatastoreBrowserSearchResults> results = new ArrayList<>();
+
+ HostDatastoreBrowserSearchResults r1 = new HostDatastoreBrowserSearchResults();
+ FileInfo f1 = new FileInfo();
+ f1.setPath(fileName);
+ r1.getFile().add(f1);
+ r1.setFolderPath("[252d36c96cfb32f48ce7756ccb79ae37] .snapshot/hourly.2017-02-23_1705/i-2-5-VM/");
+
+ HostDatastoreBrowserSearchResults r2 = new HostDatastoreBrowserSearchResults();
+ FileInfo f2 = new FileInfo();
+ f2.setPath(fileName);
+ r2.getFile().add(f2);
+ r2.setFolderPath("[252d36c96cfb32f48ce7756ccb79ae37] .snapshot/hourly.2017-02-23_1605/i-2-5-VM/");
+
+ HostDatastoreBrowserSearchResults r3 = new HostDatastoreBrowserSearchResults();
+ FileInfo f3 = new FileInfo();
+ f3.setPath(fileName);
+ r3.getFile().add(f3);
+ r3.setFolderPath("[252d36c96cfb32f48ce7756ccb79ae37] i-2-5-VM/");
+
+ results.add(r1);
+ results.add(r2);
+ results.add(r3);
+
+ when(browserMo.searchDatastore(any(String.class), any(String.class), eq(true))).thenReturn(null);
+ when(browserMo.searchDatastoreSubFolders(any(String.class),any(String.class), any(Boolean.class) )).thenReturn(results);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+
+ }
+
+ @Test
+ public void testSearchFileInSubFolders() throws Exception {
+ assertEquals("Unexpected Behavior: search should exclude .snapshot folder", "[252d36c96cfb32f48ce7756ccb79ae37] i-2-5-VM/ROOT-5.vmdk", datastoreMO.searchFileInSubFolders(fileName, false, ".snapshot") );
+ }
+
+ @Test
+ public void testSearchFileInSubFoldersWithExcludeMultipleFolders() throws Exception {
+ assertEquals("Unexpected Behavior: search should exclude folders", datastoreMO.searchFileInSubFolders(fileName, false, "i-2-5-VM, .snapshot/hourly.2017-02-23_1705"), "[252d36c96cfb32f48ce7756ccb79ae37] .snapshot/hourly.2017-02-23_1605/i-2-5-VM/ROOT-5.vmdk" );
+ }
+
+}
\ No newline at end of file
diff --git a/vmware-base/test/com/cloud/hypervisor/vmware/mo/HypervisorHostHelperTest.java b/vmware-base/test/com/cloud/hypervisor/vmware/mo/HypervisorHostHelperTest.java
index 2fc9995091b..545104d91fc 100644
--- a/vmware-base/test/com/cloud/hypervisor/vmware/mo/HypervisorHostHelperTest.java
+++ b/vmware-base/test/com/cloud/hypervisor/vmware/mo/HypervisorHostHelperTest.java
@@ -16,31 +16,40 @@
// under the License.
package com.cloud.hypervisor.vmware.mo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
import com.cloud.hypervisor.vmware.util.VmwareContext;
+import com.cloud.offering.NetworkOffering;
import com.vmware.vim25.AboutInfo;
import com.vmware.vim25.BoolPolicy;
import com.vmware.vim25.DVPortgroupConfigInfo;
import com.vmware.vim25.DVPortgroupConfigSpec;
+import com.vmware.vim25.DVSSecurityPolicy;
import com.vmware.vim25.DVSTrafficShapingPolicy;
+import com.vmware.vim25.HostNetworkSecurityPolicy;
import com.vmware.vim25.LongPolicy;
import com.vmware.vim25.ServiceContent;
import com.vmware.vim25.VMwareDVSPortSetting;
+import com.vmware.vim25.VmwareDistributedVirtualSwitchTrunkVlanSpec;
import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanIdSpec;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
+import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanSpec;
public class HypervisorHostHelperTest {
@Mock
@@ -774,4 +783,104 @@ public void testOvfDomRewriter() {
"</Envelope>";
assertEquals(expected, HypervisorHostHelper.removeOVFNetwork(ovfString));
}
+
+ private Map<NetworkOffering.Detail, String> getSecurityDetails() {
+ final Map<NetworkOffering.Detail, String> details = new HashMap<>();
+ details.put(NetworkOffering.Detail.PromiscuousMode, "false");
+ details.put(NetworkOffering.Detail.ForgedTransmits, "false");
+ details.put(NetworkOffering.Detail.MacAddressChanges, "false");
+ return details;
+ }
+
+ @Test
+ public void testVSSecurityPolicyDefault() {
+ HostNetworkSecurityPolicy secPolicy = HypervisorHostHelper.createVSSecurityPolicy(null);
+ assertFalse(secPolicy.isAllowPromiscuous());
+ assertTrue(secPolicy.isForgedTransmits());
+ assertTrue(secPolicy.isMacChanges());
+ }
+
+ @Test
+ public void testVSSecurityPolicyDefaultWithDetail() {
+ HostNetworkSecurityPolicy secPolicy = HypervisorHostHelper.createVSSecurityPolicy(getSecurityDetails());
+ assertFalse(secPolicy.isAllowPromiscuous());
+ assertFalse(secPolicy.isForgedTransmits());
+ assertFalse(secPolicy.isMacChanges());
+ }
+
+ @Test
+ public void testVSSecurityPolicyWithDetail() {
+ Map<NetworkOffering.Detail, String> details = getSecurityDetails();
+ details.put(NetworkOffering.Detail.MacAddressChanges, "true");
+ HostNetworkSecurityPolicy secPolicy = HypervisorHostHelper.createVSSecurityPolicy(details);
+ assertFalse(secPolicy.isAllowPromiscuous());
+ assertFalse(secPolicy.isForgedTransmits());
+ assertTrue(secPolicy.isMacChanges());
+ }
+
+ @Test
+ public void testDVSSecurityPolicyDefault() {
+ DVSSecurityPolicy secPolicy = HypervisorHostHelper.createDVSSecurityPolicy(null);
+ assertFalse(secPolicy.getAllowPromiscuous().isValue());
+ assertTrue(secPolicy.getForgedTransmits().isValue());
+ assertTrue(secPolicy.getMacChanges().isValue());
+ }
+
+ @Test
+ public void testDVSSecurityPolicyDefaultWithDetail() {
+ Map<NetworkOffering.Detail, String> details = getSecurityDetails();
+ details.remove(NetworkOffering.Detail.ForgedTransmits);
+ details.remove(NetworkOffering.Detail.PromiscuousMode);
+ DVSSecurityPolicy secPolicy = HypervisorHostHelper.createDVSSecurityPolicy(details);
+ assertFalse(secPolicy.getAllowPromiscuous().isValue());
+ assertFalse(secPolicy.getMacChanges().isValue());
+ assertTrue(secPolicy.getForgedTransmits().isValue());
+ }
+
+ @Test
+ public void testDVSSecurityPolicyWithDetail() {
+ Map<NetworkOffering.Detail, String> details = getSecurityDetails();
+ details.put(NetworkOffering.Detail.ForgedTransmits, "true");
+ DVSSecurityPolicy secPolicy = HypervisorHostHelper.createDVSSecurityPolicy(details);
+ assertFalse(secPolicy.getAllowPromiscuous().isValue());
+ assertTrue(secPolicy.getForgedTransmits().isValue());
+ assertFalse(secPolicy.getMacChanges().isValue());
+ }
+
+ @Test
+ public void testCreateDVPortVlanSpecNullVlanId() {
+ VmwareDistributedVirtualSwitchVlanSpec spec = HypervisorHostHelper.createDVPortVlanSpec(null, null);
+ assertTrue(spec instanceof VmwareDistributedVirtualSwitchVlanIdSpec);
+ assertTrue(((VmwareDistributedVirtualSwitchVlanIdSpec) spec).getVlanId() == 0);
+ }
+
+ @Test
+ public void testCreateDVPortVlanSpecValidVlanId() {
+ VmwareDistributedVirtualSwitchVlanSpec spec = HypervisorHostHelper.createDVPortVlanSpec(100, "400");
+ assertTrue(spec instanceof VmwareDistributedVirtualSwitchVlanIdSpec);
+ assertTrue(((VmwareDistributedVirtualSwitchVlanIdSpec) spec).getVlanId() == 100);
+ }
+
+ @Test
+ public void testCreateDVPortVlanSpecValidVlanRange() {
+ VmwareDistributedVirtualSwitchVlanSpec spec = HypervisorHostHelper.createDVPortVlanSpec(null, "200-250");
+ assertTrue(spec instanceof VmwareDistributedVirtualSwitchTrunkVlanSpec);
+ assertTrue(((VmwareDistributedVirtualSwitchTrunkVlanSpec) spec).getVlanId().get(0).getStart() == 200);
+ assertTrue(((VmwareDistributedVirtualSwitchTrunkVlanSpec) spec).getVlanId().get(0).getEnd() == 250);
+ }
+
+ @Test
+ public void testCreateDVPortVlanSpecInvalidMissingVlanRange() {
+ VmwareDistributedVirtualSwitchVlanSpec spec = HypervisorHostHelper.createDVPortVlanSpec(null, "200-");
+ assertTrue(spec instanceof VmwareDistributedVirtualSwitchVlanIdSpec);
+ assertTrue(((VmwareDistributedVirtualSwitchVlanIdSpec) spec).getVlanId() == 0);
+ }
+
+ @Test
+ public void testCreateDVPortVlanSpecInvalidInputVlanRange() {
+ VmwareDistributedVirtualSwitchVlanSpec spec = HypervisorHostHelper.createDVPortVlanSpec(null, "a-b");
+ assertTrue(spec instanceof VmwareDistributedVirtualSwitchTrunkVlanSpec);
+ assertTrue(((VmwareDistributedVirtualSwitchTrunkVlanSpec) spec).getVlanId().get(0).getStart() == 0);
+ assertTrue(((VmwareDistributedVirtualSwitchTrunkVlanSpec) spec).getVlanId().get(0).getEnd() == 0);
+ }
}
diff --git a/vmware-base/test/com/cloud/hypervisor/vmware/mo/VirtualMachineMOTest.java b/vmware-base/test/com/cloud/hypervisor/vmware/mo/VirtualMachineMOTest.java
new file mode 100644
index 00000000000..0e61b591bba
--- /dev/null
+++ b/vmware-base/test/com/cloud/hypervisor/vmware/mo/VirtualMachineMOTest.java
@@ -0,0 +1,120 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.hypervisor.vmware.mo;
+
+
+import com.cloud.hypervisor.vmware.util.VmwareClient;
+import com.cloud.hypervisor.vmware.util.VmwareContext;
+import com.vmware.vim25.ManagedObjectReference;
+import com.vmware.vim25.VirtualDevice;
+import com.vmware.vim25.VirtualLsiLogicController;
+import com.vmware.vim25.VirtualLsiLogicSASController;
+import com.vmware.vim25.VirtualSCSIController;
+import com.vmware.vim25.VirtualSCSISharing;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class VirtualMachineMOTest {
+
+ @Mock
+ VmwareContext context;
+ @Mock
+ VmwareClient client;
+ @Mock
+ ManagedObjectReference mor;
+
+ VirtualMachineMO vmMo;
+
+ private List<VirtualDevice> getVirtualScSiDeviceList(Class<?> cls) {
+
+ List<VirtualDevice> deviceList = new ArrayList<>();
+ try {
+
+ VirtualSCSIController scsiController = (VirtualSCSIController)cls.newInstance();
+ scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
+ scsiController.setBusNumber(0);
+ scsiController.setKey(1);
+ deviceList.add(scsiController);
+ }
+ catch (Exception ex) {
+
+ }
+ return deviceList;
+ }
+
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ vmMo = new VirtualMachineMO(context, mor);
+ when(context.getVimClient()).thenReturn(client);
+ }
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ @Test
+ public void testEnsureScsiDeviceController() {
+ try {
+ when(client.getDynamicProperty(any(ManagedObjectReference.class), any(String.class))).thenReturn(getVirtualScSiDeviceList(VirtualLsiLogicSASController.class));
+ vmMo.ensureScsiDeviceController();
+ }
+ catch (Exception e) {
+ fail("Received exception when success expected: " + e.getMessage());
+ }
+ }
+
+ @Test
+ public void TestEnsureLsiLogicDeviceControllers() {
+ try {
+ when(client.getDynamicProperty(any(ManagedObjectReference.class), any(String.class))).thenReturn(getVirtualScSiDeviceList(VirtualLsiLogicController.class));
+ vmMo.ensureLsiLogicDeviceControllers(1, 0);
+ }
+ catch (Exception e) {
+ fail("Received exception when success expected: " + e.getMessage());
+ }
+
+ }
+}
\ No newline at end of file
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
With regards,
Apache Git Services