Merging 4.2-forward into 4.2
|
|
@ -17,6 +17,8 @@
|
|||
# under the License.
|
||||
from cloudutils.networkConfig import networkConfig
|
||||
from cloudutils.utilities import bash
|
||||
import logging
|
||||
import re
|
||||
def isOldStyleBridge(brName):
|
||||
if brName.find("cloudVirBr") == 0:
|
||||
return True
|
||||
|
|
@ -33,6 +35,17 @@ def upgradeBridgeName(brName, enslavedDev):
|
|||
bash("ip link set %s down"%brName)
|
||||
bash("ip link set %s name %s"%(brName, newBrName))
|
||||
bash("ip link set %s up" %newBrName)
|
||||
cmd = "iptables-save | grep FORWARD | grep -w " + brName
|
||||
rules = bash(cmd).stdout.split('\n')
|
||||
rules.pop()
|
||||
for rule in rules:
|
||||
try:
|
||||
delrule = re.sub("-A", "-D", rule)
|
||||
newrule = re.sub(" " + brName + " ", " " + newBrName + " ", rule)
|
||||
bash("iptables " + delrule)
|
||||
bash("iptables " + newrule)
|
||||
except:
|
||||
logging.exception("Ignoring failure to update rules for rule " + rule + " on bridge " + brName)
|
||||
if __name__ == '__main__':
|
||||
netlib = networkConfig()
|
||||
bridges = netlib.listNetworks()
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ public class ConsoleProxyResource extends ServerResourceBase implements
|
|||
}
|
||||
|
||||
private Answer execute(StartConsoleProxyAgentHttpHandlerCommand cmd) {
|
||||
s_logger.info("Invoke launchConsoleProxy() in responding to StartConsoleProxyAgentHttpHandlerCommand");
|
||||
launchConsoleProxy(cmd.getKeystoreBits(), cmd.getKeystorePassword(), cmd.getEncryptorPassword());
|
||||
return new Answer(cmd);
|
||||
}
|
||||
|
|
@ -361,29 +362,31 @@ public class ConsoleProxyResource extends ServerResourceBase implements
|
|||
try {
|
||||
Class<?> consoleProxyClazz = Class.forName("com.cloud.consoleproxy.ConsoleProxy");
|
||||
try {
|
||||
s_logger.info("Invoke setEncryptorPassword(), ecnryptorPassword: " + encryptorPassword);
|
||||
Method methodSetup = consoleProxyClazz.getMethod(
|
||||
"setEncryptorPassword", String.class);
|
||||
methodSetup.invoke(null, encryptorPassword);
|
||||
|
||||
s_logger.info("Invoke startWithContext()");
|
||||
Method method = consoleProxyClazz.getMethod(
|
||||
"startWithContext", Properties.class,
|
||||
Object.class, byte[].class, String.class);
|
||||
method.invoke(null, _properties, resource, ksBits,
|
||||
ksPassword);
|
||||
} catch (SecurityException e) {
|
||||
s_logger.error("Unable to launch console proxy due to SecurityException");
|
||||
s_logger.error("Unable to launch console proxy due to SecurityException", e);
|
||||
System.exit(ExitStatus.Error.value());
|
||||
} catch (NoSuchMethodException e) {
|
||||
s_logger.error("Unable to launch console proxy due to NoSuchMethodException");
|
||||
s_logger.error("Unable to launch console proxy due to NoSuchMethodException", e);
|
||||
System.exit(ExitStatus.Error.value());
|
||||
} catch (IllegalArgumentException e) {
|
||||
s_logger.error("Unable to launch console proxy due to IllegalArgumentException");
|
||||
s_logger.error("Unable to launch console proxy due to IllegalArgumentException", e);
|
||||
System.exit(ExitStatus.Error.value());
|
||||
} catch (IllegalAccessException e) {
|
||||
s_logger.error("Unable to launch console proxy due to IllegalAccessException");
|
||||
s_logger.error("Unable to launch console proxy due to IllegalAccessException", e);
|
||||
System.exit(ExitStatus.Error.value());
|
||||
} catch (InvocationTargetException e) {
|
||||
s_logger.error("Unable to launch console proxy due to InvocationTargetException");
|
||||
s_logger.error("Unable to launch console proxy due to InvocationTargetException " + e.getTargetException().toString(), e);
|
||||
System.exit(ExitStatus.Error.value());
|
||||
}
|
||||
} catch (final ClassNotFoundException e) {
|
||||
|
|
@ -402,22 +405,22 @@ public class ConsoleProxyResource extends ServerResourceBase implements
|
|||
Method methodSetup = consoleProxyClazz.getMethod("setEncryptorPassword", String.class);
|
||||
methodSetup.invoke(null, encryptorPassword);
|
||||
} catch (SecurityException e) {
|
||||
s_logger.error("Unable to launch console proxy due to SecurityException");
|
||||
s_logger.error("Unable to launch console proxy due to SecurityException", e);
|
||||
System.exit(ExitStatus.Error.value());
|
||||
} catch (NoSuchMethodException e) {
|
||||
s_logger.error("Unable to launch console proxy due to NoSuchMethodException");
|
||||
s_logger.error("Unable to launch console proxy due to NoSuchMethodException", e);
|
||||
System.exit(ExitStatus.Error.value());
|
||||
} catch (IllegalArgumentException e) {
|
||||
s_logger.error("Unable to launch console proxy due to IllegalArgumentException");
|
||||
s_logger.error("Unable to launch console proxy due to IllegalArgumentException", e);
|
||||
System.exit(ExitStatus.Error.value());
|
||||
} catch (IllegalAccessException e) {
|
||||
s_logger.error("Unable to launch console proxy due to IllegalAccessException");
|
||||
s_logger.error("Unable to launch console proxy due to IllegalAccessException", e);
|
||||
System.exit(ExitStatus.Error.value());
|
||||
} catch (InvocationTargetException e) {
|
||||
s_logger.error("Unable to launch console proxy due to InvocationTargetException");
|
||||
s_logger.error("Unable to launch console proxy due to InvocationTargetException " + e.getTargetException().toString(), e);
|
||||
System.exit(ExitStatus.Error.value());
|
||||
} catch (final ClassNotFoundException e) {
|
||||
s_logger.error("Unable to launch console proxy due to ClassNotFoundException");
|
||||
s_logger.error("Unable to launch console proxy due to ClassNotFoundException", e);
|
||||
System.exit(ExitStatus.Error.value());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -443,6 +443,7 @@ public class EventTypes {
|
|||
public static final String EVENT_CLEANUP_VM_RESERVATION = "VM.RESERVATION.CLEANUP";
|
||||
|
||||
public static final String EVENT_UCS_ASSOCIATED_PROFILE = "UCS.ASSOCIATEPROFILE";
|
||||
public static final String EVENT_UCS_DISASSOCIATED_PROFILE = "UCS.DISASSOCIATEPROFILE";
|
||||
|
||||
static {
|
||||
|
||||
|
|
|
|||
|
|
@ -527,6 +527,9 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
|
|||
} catch (ConcurrentOperationException ex) {
|
||||
s_logger.warn("Exception: ", ex);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
|
||||
} catch (ResourceAllocationException ex) {
|
||||
s_logger.warn("Exception: ", ex);
|
||||
throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -617,7 +617,8 @@ listUcsManagers=1
|
|||
listUcsProfiles=1
|
||||
listUcsBlades=1
|
||||
associateUcsProfileToBlade=1
|
||||
removedeleteUcsManager=1
|
||||
deleteUcsManager=1
|
||||
disassociateUcsProfileFromBlade=1
|
||||
|
||||
#### New Load Balancer commands
|
||||
createLoadBalancer=15
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
/etc/init.d/cloudstack-agent
|
||||
/usr/bin/cloudstack-setup-agent
|
||||
/usr/bin/cloudstack-ssh
|
||||
/usr/bin/cloudstack-agent-upgrade
|
||||
/var/log/cloudstack/agent
|
||||
/usr/share/cloudstack-agent/lib/*
|
||||
/usr/share/cloudstack-agent/plugins
|
||||
|
|
|
|||
|
|
@ -34,7 +34,15 @@ case "$1" in
|
|||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Running cloudstack-agent-upgrade to update bridge name for upgrade from CloudStack 4.0.x (and before) to CloudStack 4.1 (and later)
|
||||
/usr/bin/cloudstack-agent-upgrade
|
||||
if [ ! -d "/etc/libvirt/hooks" ] ; then
|
||||
mkdir /etc/libvirt/hooks
|
||||
fi
|
||||
cp -a /usr/share/cloudstack-agent/lib/libvirtqemuhook /etc/libvirt/hooks/qemu
|
||||
/etc/init.d/libvirt-bin restart
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
exit 0
|
||||
|
|
|
|||
|
|
@ -27,11 +27,17 @@ case "$1" in
|
|||
cp -a /etc/cloud/management/db.properties /etc/cloudstack/usage/db.properties
|
||||
fi
|
||||
|
||||
# Replacing db.properties with management server db.properties
|
||||
if [ -f "/etc/cloudstack/management/db.properties" ]; then
|
||||
rm -rf /etc/cloudstack/usage/db.properties
|
||||
ln -s /etc/cloudstack/management/db.properties /etc/cloudstack/usage/db.properties
|
||||
fi
|
||||
|
||||
# We also retain the log4j configuration
|
||||
if [ -f "/etc/cloud/usage/log4j-cloud_usage.xml" ]; then
|
||||
cp -a /etc/cloud/usage/log4j-cloud_usage.xml /etc/cloudstack/usage/log4j-cloud_usage.xml
|
||||
if [ -f "/etc/cloud/usage/log4j-cloud.xml" ]; then
|
||||
cp -a /etc/cloud/usage/log4j-cloud.xml /etc/cloudstack/usage/log4j-cloud.xml
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
exit 0
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ install:
|
|||
install -D packaging/debian/init/cloud-agent $(DESTDIR)/$(SYSCONFDIR)/init.d/$(PACKAGE)-agent
|
||||
install -D agent/target/transformed/cloud-setup-agent $(DESTDIR)/usr/bin/cloudstack-setup-agent
|
||||
install -D agent/target/transformed/cloud-ssh $(DESTDIR)/usr/bin/cloudstack-ssh
|
||||
install -D agent/target/transformed/cloudstack-agent-upgrade $(DESTDIR)/usr/bin/cloudstack-agent-upgrade
|
||||
install -D agent/target/transformed/libvirtqemuhook $(DESTDIR)/usr/share/$(PACKAGE)-agent/lib/
|
||||
install -D agent/target/transformed/* $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/agent
|
||||
|
||||
# cloudstack-management
|
||||
|
|
@ -145,7 +147,8 @@ install:
|
|||
mkdir $(DESTDIR)/usr/share/$(PACKAGE)-usage/plugins
|
||||
install -D usage/target/cloud-usage-$(VERSION).jar $(DESTDIR)/usr/share/$(PACKAGE)-usage/lib/$(PACKAGE)-usage.jar
|
||||
install -D usage/target/dependencies/* $(DESTDIR)/usr/share/$(PACKAGE)-usage/lib/
|
||||
cp usage/target/transformed/* $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/usage/
|
||||
cp usage/target/transformed/db.properties $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/usage/
|
||||
cp usage/target/transformed/log4j-cloud_usage.xml $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/usage/log4j-cloud.xml
|
||||
install -D packaging/debian/init/cloud-usage $(DESTDIR)/$(SYSCONFDIR)/init.d/$(PACKAGE)-usage
|
||||
|
||||
# cloudstack-awsapi
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
<?xml version='1.0' encoding='utf-8' ?>
|
||||
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||
<!ENTITY % BOOK_ENTITIES SYSTEM "cloudstack.ent">
|
||||
%BOOK_ENTITIES;
|
||||
]>
|
||||
|
||||
<!-- 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.
|
||||
-->
|
||||
|
||||
<section id="accessing-system-vms">
|
||||
<title>Accessing System VMs</title>
|
||||
<para>It may sometimes be necessary to access System VMs for diagnostics of certain issues, for example if you are experiencing SSVM (Secondary Storage VM) connection issues. Use the steps below in order to connect to the SSH console of a running System VM.</para>
|
||||
<para>
|
||||
Accessing System VMs over the network requires the use of private keys and connecting to System VMs SSH Daemon on port 3922.
|
||||
XenServer/KVM Hypervisors store this key at /root/.ssh/id_rsa.cloud on each &PRODUCT; agent.
|
||||
To access System VMs running on ESXi, the key is stored on the management server at /var/lib/cloudstack/management/.ssh/id_rsa.
|
||||
</para>
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<para>Find the details of the System VM</para>
|
||||
<orderedlist numeration="loweralpha">
|
||||
<listitem><para>Log in with admin privileges to the &PRODUCT; UI.</para></listitem>
|
||||
<listitem><para>Click Infrastructure, then System VMs, and then click the name of a running VM.</para></listitem>
|
||||
<listitem><para>Take a note of the 'Host', 'Private IP Address' and 'Link Local IP Address' of the System VM you wish to access.</para></listitem>
|
||||
</orderedlist>
|
||||
<para><inlinegraphic format="PNG" fileref="images/view-systemvm-details.png"/></para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>XenServer/KVM Hypervisors</para>
|
||||
<orderedlist numeration="loweralpha">
|
||||
<listitem><para>Connect to the Host of which the System VM is running.</para></listitem>
|
||||
<listitem><para>SSH the 'Link Local IP Address' of the System VM from the Host on which the VM is running.</para></listitem>
|
||||
<listitem><para>Format: ssh -i <path-to-private-key> <link-local-ip> -p 3922</para></listitem>
|
||||
<listitem><para>Example: root@faith:~# ssh -i /root/.ssh/id_rsa.cloud 169.254.3.93 -p 3922</para></listitem>
|
||||
</orderedlist>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>ESXi Hypervisors</para>
|
||||
<orderedlist numeration="loweralpha">
|
||||
<listitem><para>Connect to your &PRODUCT; Management Server.</para></listitem>
|
||||
<listitem><para>ESXi users should SSH to the private IP address of the System VM.</para></listitem>
|
||||
<listitem><para>Format: ssh -i <path-to-private-key> <vm-private-ip> -p 3922</para></listitem>
|
||||
<listitem><para>Example: root@management:~# ssh -i /var/lib/cloudstack/management/.ssh/id_rsa 172.16.0.250 -p 3922</para></listitem>
|
||||
</orderedlist>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
|
@ -0,0 +1,364 @@
|
|||
<?xml version='1.0' encoding='utf-8' ?>
|
||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "file:///C:/Program%20Files%20(x86)/Publican/DocBook_DTD/docbookx.dtd" [
|
||||
<!ENTITY % BOOK_ENTITIES SYSTEM "cloudstack.ent">
|
||||
%BOOK_ENTITIES;
|
||||
]>
|
||||
<!-- 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.
|
||||
-->
|
||||
<chapter id="third-party-ui-plugin">
|
||||
<!-- CLOUDSTACK-883 -->
|
||||
<title>Third-Party UI Plugin Framework</title>
|
||||
<para>Using the new third-party plugin framework, you can write and install extensions to
|
||||
&PRODUCT;. The installed and enabled plugins will appear in the UI alongside the
|
||||
other features.
|
||||
The code for the plugin is simply placed in a special directory
|
||||
within &PRODUCT;’s installed code at any time after &PRODUCT; installation. The new plugin
|
||||
appears only when it is enabled by the cloud administrator.</para>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="./images/plugin_intro.jpg"/>
|
||||
</imageobject>
|
||||
<textobject>
|
||||
<phrase>plugin_intro.jpg: New plugin button in product navbar</phrase>
|
||||
</textobject>
|
||||
</mediaobject>
|
||||
<para>The left navigation bar of the &PRODUCT; UI has a new Plugins button to help you work with UI plugins.</para>
|
||||
<section id="plugin-howto-overview">
|
||||
<title>How to Write a Plugin: Overview</title>
|
||||
<para>The basic procedure for writing a plugin is:</para>
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<para>Write the code and create the other files needed. You will need the plugin code
|
||||
itself (in Javascript), a thumbnail image, the plugin listing, and a CSS file.</para>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="./images/plugin1.jpg"/>
|
||||
</imageobject>
|
||||
<textobject>
|
||||
<phrase>plugin1.jpg: Write the plugin code</phrase>
|
||||
</textobject>
|
||||
</mediaobject>
|
||||
<para>All UI plugins have the following set of files:</para>
|
||||
<programlisting>+-- cloudstack/
|
||||
+-- ui/
|
||||
+-- plugins/
|
||||
+-- csMyFirstPlugin/
|
||||
+-- config.js --> Plugin metadata (title, author, vendor URL, etc.)
|
||||
+-- icon.png --> Icon, shown on side nav bar and plugin listing
|
||||
(should be square, and ~50x50px)
|
||||
+-- csMyFirstPlugin.css --> CSS file, loaded automatically when plugin loads
|
||||
+-- csMyFirstPlugin.js --> Main JS file, containing plugin code
|
||||
</programlisting>
|
||||
<para>The same files must also be present at /tomcat/webapps/client/plugins.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>The &PRODUCT; administrator adds the folder containing your plugin code under the
|
||||
&PRODUCT; PLUGINS folder.</para>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="./images/plugin2.jpg"/>
|
||||
</imageobject>
|
||||
<textobject>
|
||||
<phrase>plugin2.jpg: The plugin code is placed in the PLUGINS folder</phrase>
|
||||
</textobject>
|
||||
</mediaobject>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>The administrator also adds the name of your plugin to the plugin.js file in the
|
||||
PLUGINS folder.</para>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="./images/plugin3.jpg"/>
|
||||
</imageobject>
|
||||
<textobject>
|
||||
<phrase>plugin3.jpg: The plugin name is added to plugin.js in the PLUGINS
|
||||
folder</phrase>
|
||||
</textobject>
|
||||
</mediaobject>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>The next time the user refreshes the UI in the browser, your plugin will appear in
|
||||
the left navigation bar.</para>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="./images/plugin4.jpg"/>
|
||||
</imageobject>
|
||||
<textobject>
|
||||
<phrase>plugin4.jpg: The plugin appears in the UI</phrase>
|
||||
</textobject>
|
||||
</mediaobject>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
</section>
|
||||
<section id="plugin-howto-details">
|
||||
<title>How to Write a Plugin: Implementation Details</title>
|
||||
<para>This section requires an understanding of JavaScript and the &PRODUCT; API. You don't
|
||||
need knowledge of specific frameworks for this tutorial (jQuery, etc.), since the
|
||||
&PRODUCT; UI handles the front-end rendering for you.</para>
|
||||
<para>There is much more to the &PRODUCT; UI framework than can be described here. The UI is
|
||||
very flexible to handle many use cases, so there are countless options and variations. The
|
||||
best reference right now is to read the existing code for the main UI, which is in the /ui
|
||||
folder. Plugins are written in a very similar way to the main UI.</para>
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<para><emphasis role="bold">Create the directory to hold your plugin.</emphasis></para>
|
||||
<para>All plugins are composed of set of required files in the directory
|
||||
/ui/plugins/pluginID, where pluginID is a short name for your plugin. It's recommended
|
||||
that you prefix your folder name (for example, bfMyPlugin) to avoid naming conflicts
|
||||
with other people's plugins.</para>
|
||||
<para>In this example, the plugin is named csMyFirstPlugin.</para>
|
||||
<programlisting>$ cd cloudstack/ui/plugins
|
||||
$ mkdir csMyFirstPlugin
|
||||
$ ls -l
|
||||
|
||||
total 8
|
||||
drwxr-xr-x 2 bgregory staff 68 Feb 11 14:44 csMyFirstPlugin
|
||||
-rw-r--r-- 1 bgregory staff 101 Feb 11 14:26 plugins.js
|
||||
</programlisting>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><emphasis role="bold">Change to your new plugin directory.</emphasis></para>
|
||||
<programlisting>$ cd csMyFirstPlugin
|
||||
</programlisting>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><emphasis role="bold">Set up the listing.</emphasis></para>
|
||||
<para>Add the file config.js, using your favorite editor.</para>
|
||||
<programlisting>$ vi config.js</programlisting>
|
||||
<para>Add the following content to config.js. This information will be displayed on the
|
||||
plugin listing page in the UI:</para>
|
||||
<programlisting>(function (cloudStack) {
|
||||
cloudStack.plugins.csMyFirstPlugin.config = {
|
||||
title: 'My first plugin',
|
||||
desc: 'Tutorial plugin',
|
||||
externalLink: 'http://www.cloudstack.org/',
|
||||
authorName: 'Test Plugin Developer',
|
||||
authorEmail: 'plugin.developer@example.com'
|
||||
};
|
||||
}(cloudStack));
|
||||
</programlisting>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><emphasis role="bold">Add a new main section.</emphasis></para>
|
||||
<para>Add the file csMyFirstPlugin.js, using your favorite editor.</para>
|
||||
<programlisting>$ vi csMyFirstPlugin.js</programlisting>
|
||||
<para>Add the following content to csMyFirstPlugin.js:</para>
|
||||
<programlisting>(function (cloudStack) {
|
||||
cloudStack.plugins.csMyFirstPlugin = function(plugin) {
|
||||
plugin.ui.addSection({
|
||||
id: 'csMyFirstPlugin',
|
||||
title: 'My Plugin',
|
||||
preFilter: function(args) {
|
||||
return isAdmin();
|
||||
},
|
||||
show: function() {
|
||||
return $('<div>').html('Content will go here');
|
||||
}
|
||||
});
|
||||
};
|
||||
}(cloudStack));
|
||||
</programlisting>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><emphasis role="bold">Register the plugin.</emphasis></para>
|
||||
<para>You now have the minimal content needed to run the plugin, so you can activate the
|
||||
plugin in the UI by adding it to plugins.js. First, edit the file:</para>
|
||||
<programlisting>$ cd cloudstack/ui/plugins
|
||||
$ vi plugins.js
|
||||
</programlisting>
|
||||
<para>Now add the following to plugins.js:</para>
|
||||
<programlisting>(function($, cloudStack) {
|
||||
cloudStack.plugins = [
|
||||
'csMyFirstPlugin'
|
||||
];
|
||||
}(jQuery, cloudStack));
|
||||
</programlisting>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><emphasis role="bold">Check the plugin in the UI.</emphasis></para>
|
||||
<para>First, copy all the plugin code that you have created so far to
|
||||
/tomcat/webapps/client/plugins. Then refresh the browser and click Plugins in the side
|
||||
navigation bar. You should see your new plugin.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><emphasis role="bold">Make the plugin do something.</emphasis></para>
|
||||
<para>Right now, you just have placeholder content in the new plugin. It's time to add
|
||||
real code. In this example, you will write a basic list view, which renders data from
|
||||
an API call. You will list all virtual machines owned by the logged-in user. To do
|
||||
this, replace the 'show' function in the plugin code with a 'listView' block,
|
||||
containing the required syntax for a list view. To get the data, use the
|
||||
listVirtualMachines API call. Without any parameters, it will return VMs only for your
|
||||
active user. Use the provided 'apiCall' helper method to handle the server call. Of
|
||||
course, you are free to use any other method for making the AJAX call (for example,
|
||||
jQuery's $.ajax method).</para>
|
||||
<para>First, open your plugin's JavaScript source file in your favorite editor:</para>
|
||||
<programlisting>$ cd csMyFirstPlugin
|
||||
$ vi csMyFirstPlugin.js
|
||||
</programlisting>
|
||||
<para>Add the following code in csMyFirstPlugin.js:</para>
|
||||
<programlisting>(function (cloudStack) {
|
||||
cloudStack.plugins.csMyFirstPlugin = function(plugin) {
|
||||
plugin.ui.addSection({
|
||||
id: 'csMyFirstPlugin',
|
||||
title: 'My Plugin',
|
||||
preFilter: function(args) {
|
||||
return isAdmin();
|
||||
},
|
||||
|
||||
// Render page as a list view
|
||||
listView: {
|
||||
id: 'testPluginInstances',
|
||||
fields: {
|
||||
name: { label: 'label.name' },
|
||||
instancename: { label: 'label.internal.name' },
|
||||
displayname: { label: 'label.display.name' },
|
||||
zonename: { label: 'label.zone.name' }
|
||||
},
|
||||
dataProvider: function(args) {
|
||||
// API calls go here, to retrive the data asynchronously
|
||||
//
|
||||
// On successful retrieval, call
|
||||
// args.response.success({ data: [data array] });
|
||||
plugin.ui.apiCall('listVirtualMachines', {
|
||||
success: function(json) {
|
||||
var vms = json.listvirtualmachinesresponse.virtualmachine;
|
||||
|
||||
args.response.success({ data: vms });
|
||||
},
|
||||
error: function(errorMessage) {
|
||||
args.response.error(errorMessage)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}(cloudStack));
|
||||
</programlisting>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><emphasis role="bold">Test the plugin.</emphasis></para>
|
||||
<para>First, copy all the plugin code that you have created so far to
|
||||
/tomcat/webapps/client/plugins. Then refresh the browser. You can see that your
|
||||
placeholder content was replaced with a list table, containing 4 columns of virtual
|
||||
machine data.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><emphasis role="bold">Add an action button.</emphasis></para>
|
||||
<para>Let's add an action button to the list view, which will reboot the VM. To do this,
|
||||
add an actions block under listView. After specifying the correct format, the actions
|
||||
will appear automatically to the right of each row of data.</para>
|
||||
<programlisting>$ vi csMyFirstPlugin.js
|
||||
</programlisting>
|
||||
<para>Now add the following new code in csMyFirstPlugin.js. (The dots ... show where we
|
||||
have omitted some existing code for the sake of space. Don't actually cut and paste
|
||||
that part):</para>
|
||||
<programlisting>...
|
||||
listView: {
|
||||
id: 'testPluginInstances',
|
||||
...
|
||||
|
||||
actions: {
|
||||
// The key/ID you specify here will determine what icon is
|
||||
// shown in the UI for this action,
|
||||
// and will be added as a CSS class to the action's element
|
||||
// (i.e., '.action.restart')
|
||||
//
|
||||
// -- here, 'restart' is a predefined name in &PRODUCT; that will
|
||||
// automatically show a 'reboot' arrow as an icon;
|
||||
// this can be changed in csMyFirstPlugin.css
|
||||
restart: {
|
||||
label: 'Restart VM',
|
||||
messages: {
|
||||
confirm: function() { return 'Are you sure you want to restart this VM?' },
|
||||
notification: function() { return 'Rebooted VM' }
|
||||
},
|
||||
action: function(args) {
|
||||
// Get the instance object of the selected row from context
|
||||
//
|
||||
// -- all currently loaded state is stored in 'context' as objects,
|
||||
// such as the selected list view row,
|
||||
// the selected section, and active user
|
||||
//
|
||||
// -- for list view actions, the object's key will be the same as
|
||||
// listView.id, specified above;
|
||||
// always make sure you specify an 'id' for the listView,
|
||||
// or else it will be 'undefined!'
|
||||
var instance = args.context.testPluginInstances[0];
|
||||
|
||||
plugin.ui.apiCall('rebootVirtualMachine', {
|
||||
// These will be appended to the API request
|
||||
//
|
||||
// i.e., rebootVirtualMachine&id=...
|
||||
data: {
|
||||
id: instance.id
|
||||
},
|
||||
success: function(json) {
|
||||
args.response.success({
|
||||
// This is an async job, so success here only indicates
|
||||
// that the job was initiated.
|
||||
//
|
||||
// To pass the job ID to the notification UI
|
||||
// (for checking to see when action is completed),
|
||||
// '_custom: { jobID: ... }' needs to always be passed on success,
|
||||
// in the same format as below
|
||||
_custom: { jobId: json.rebootvirtualmachineresponse.jobid }
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
error: function(errorMessage) {
|
||||
args.response.error(errorMessage); // Cancel action, show error message returned
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// Because rebootVirtualMachine is an async job, we need to add
|
||||
// a poll function, which will perodically check
|
||||
// the management server to see if the job is ready
|
||||
// (via pollAsyncJobResult API call)
|
||||
//
|
||||
// The plugin API provides a helper function, 'plugin.ui.pollAsyncJob',
|
||||
/ which will work for most jobs
|
||||
// in &PRODUCT;
|
||||
notification: {
|
||||
poll: plugin.ui.pollAsyncJob
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
dataProvider: function(args) {
|
||||
...
|
||||
...
|
||||
</programlisting>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><emphasis role="bold">Add the thumbnail icon.</emphasis></para>
|
||||
<para>Create an icon file; it should be square, about 50x50 pixels, and named icon.png.
|
||||
Copy it into the same directory with your plugin code:
|
||||
cloudstack/ui/plugins/csMyFirstPlugin/icon.png.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><emphasis role="bold">Add the stylesheet.</emphasis></para>
|
||||
<para>Create a CSS file, with the same name as your .js file. Copy it into the same
|
||||
directory with your plugin code:
|
||||
cloudstack/ui/plugins/csMyFirstPlugin/csMyFirstPlugin.css.</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
</section>
|
||||
</chapter>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# Config::Simple 4.59
|
||||
# Fri May 25 12:50:59 2012
|
||||
# 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.
|
||||
|
||||
xml_lang: "en-US"
|
||||
type: Book
|
||||
brand: cloudstack
|
||||
docname: qig
|
||||
|
|
@ -80,4 +80,8 @@ public final class CopyCommand extends Command implements StorageSubSystemComman
|
|||
this.cacheTO = cacheTO;
|
||||
}
|
||||
|
||||
public int getWaitInMillSeconds() {
|
||||
return this.getWait() * 1000;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -340,7 +340,6 @@ public class StoragePoolVO implements StoragePool {
|
|||
|
||||
@Override
|
||||
public boolean isInMaintenance() {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
return status == StoragePoolStatus.PrepareForMaintenance || status == StoragePoolStatus.Maintenance || status == StoragePoolStatus.ErrorInMaintenance || removed != null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ import javax.inject.Inject;
|
|||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.storage.VMTemplateStorageResourceAssoc;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
|
||||
import org.apache.log4j.Logger;
|
||||
|
|
@ -70,6 +73,8 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
|
|||
VMTemplateZoneDao _templateZoneDao;
|
||||
@Inject
|
||||
VMTemplateDetailsDao _templateDetailsDao;
|
||||
@Inject
|
||||
DataStoreManager _dataStoreMgr;
|
||||
|
||||
@Inject
|
||||
ConfigurationDao _configDao;
|
||||
|
|
@ -338,6 +343,7 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
|
|||
readySystemTemplateSearch.and("templateType", readySystemTemplateSearch.entity().getTemplateType(), SearchCriteria.Op.EQ);
|
||||
SearchBuilder<TemplateDataStoreVO> templateDownloadSearch = _templateDataStoreDao.createSearchBuilder();
|
||||
templateDownloadSearch.and("downloadState", templateDownloadSearch.entity().getDownloadState(), SearchCriteria.Op.EQ);
|
||||
templateDownloadSearch.and("dataStoreId", templateDownloadSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ);
|
||||
readySystemTemplateSearch.join("vmTemplateJoinTemplateStoreRef", templateDownloadSearch, templateDownloadSearch.entity().getTemplateId(),
|
||||
readySystemTemplateSearch.entity().getId(), JoinBuilder.JoinType.INNER);
|
||||
SearchBuilder<HostVO> hostHyperSearch2 = _hostDao.createSearchBuilder();
|
||||
|
|
@ -795,7 +801,13 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
|
|||
sc.setJoinParameters("tmplHyper", "type", Host.Type.Routing);
|
||||
sc.setJoinParameters("tmplHyper", "zoneId", zoneId);
|
||||
sc.setJoinParameters("vmTemplateJoinTemplateStoreRef", "downloadState", VMTemplateStorageResourceAssoc.Status.DOWNLOADED);
|
||||
|
||||
DataStore secStore = this._dataStoreMgr.getImageStore(zoneId);
|
||||
if (secStore != null) {
|
||||
sc.setJoinParameters("vmTemplateJoinTemplateStoreRef", "dataStoreId", secStore.getId());
|
||||
} else{
|
||||
s_logger.warn("No secondary storage is available in data center " + zoneId);
|
||||
}
|
||||
|
||||
// order by descending order of id
|
||||
List<VMTemplateVO> tmplts = listBy(sc, new Filter(VMTemplateVO.class, "id", false, null, null));
|
||||
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ public class Upgrade410to420 implements DbUpgrade {
|
|||
createPlaceHolderNics(conn);
|
||||
updateRemoteAccessVpn(conn);
|
||||
updateSystemVmTemplates(conn);
|
||||
updateCluster_details(conn);
|
||||
updateOverCommitRatioClusterDetails(conn);
|
||||
updatePrimaryStore(conn);
|
||||
addEgressFwRulesForSRXGuestNw(conn);
|
||||
upgradeEIPNetworkOfferings(conn);
|
||||
|
|
@ -115,6 +115,7 @@ public class Upgrade410to420 implements DbUpgrade {
|
|||
migrateVolumeOnSecondaryStorage(conn);
|
||||
createFullCloneFlag(conn);
|
||||
upgradeVpcServiceMap(conn);
|
||||
upgradeResourceCount(conn);
|
||||
}
|
||||
|
||||
private void createFullCloneFlag(Connection conn) {
|
||||
|
|
@ -899,7 +900,7 @@ public class Upgrade410to420 implements DbUpgrade {
|
|||
}
|
||||
|
||||
//update the cluster_details table with default overcommit ratios.
|
||||
private void updateCluster_details(Connection conn) {
|
||||
private void updateOverCommitRatioClusterDetails(Connection conn) {
|
||||
PreparedStatement pstmt = null;
|
||||
PreparedStatement pstmt1 = null;
|
||||
PreparedStatement pstmt2 =null;
|
||||
|
|
@ -908,7 +909,7 @@ public class Upgrade410to420 implements DbUpgrade {
|
|||
ResultSet rscpu_global = null;
|
||||
ResultSet rsmem_global = null;
|
||||
try {
|
||||
pstmt = conn.prepareStatement("select id, hypervisor_type from `cloud`.`cluster`");
|
||||
pstmt = conn.prepareStatement("select id, hypervisor_type from `cloud`.`cluster` WHERE removed IS NULL");
|
||||
pstmt1=conn.prepareStatement("INSERT INTO `cloud`.`cluster_details` (cluster_id, name, value) VALUES(?, 'cpuOvercommitRatio', ?)");
|
||||
pstmt2=conn.prepareStatement("INSERT INTO `cloud`.`cluster_details` (cluster_id, name, value) VALUES(?, 'memoryOvercommitRatio', ?)");
|
||||
pstmt3=conn.prepareStatement("select value from `cloud`.`configuration` where name=?");
|
||||
|
|
@ -927,7 +928,7 @@ public class Upgrade410to420 implements DbUpgrade {
|
|||
while (rs1.next()) {
|
||||
long id = rs1.getLong(1);
|
||||
String hypervisor_type = rs1.getString(2);
|
||||
if (hypervisor_type.equalsIgnoreCase(HypervisorType.VMware.toString())) {
|
||||
if (HypervisorType.VMware.toString().equalsIgnoreCase(hypervisor_type)) {
|
||||
pstmt1.setLong(1,id);
|
||||
pstmt1.setString(2,global_cpu_overprovisioning_factor);
|
||||
pstmt1.execute();
|
||||
|
|
@ -2239,6 +2240,11 @@ public class Upgrade410to420 implements DbUpgrade {
|
|||
storeInsert.setDate(9, nfs_created);
|
||||
storeInsert.executeUpdate();
|
||||
}
|
||||
|
||||
s_logger.debug("Marking NFS secondary storage in host table as removed");
|
||||
pstmt = conn.prepareStatement("UPDATE `cloud`.`host` SET removed = now() WHERE type = 'SecondaryStorage' and removed is null");
|
||||
pstmt.executeUpdate();
|
||||
pstmt.close();
|
||||
}
|
||||
catch (SQLException e) {
|
||||
String msg = "Unable to migrate secondary storages." + e.getMessage();
|
||||
|
|
@ -3007,4 +3013,152 @@ public class Upgrade410to420 implements DbUpgrade {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void upgradeResourceCount(Connection conn) {
|
||||
s_logger.debug("upgradeResourceCount start");
|
||||
PreparedStatement pstmt1 = null;
|
||||
PreparedStatement pstmt2 = null;
|
||||
PreparedStatement pstmt3 = null;
|
||||
PreparedStatement pstmt4 = null;
|
||||
PreparedStatement pstmt5 = null;
|
||||
ResultSet rs = null;
|
||||
ResultSet rsAccount = null;
|
||||
ResultSet rsCount = null;
|
||||
try {
|
||||
pstmt1 = conn.prepareStatement("select id, domain_id FROM `cloud`.`account` where removed is NULL ");
|
||||
rsAccount = pstmt1.executeQuery();
|
||||
while (rsAccount.next()) {
|
||||
long account_id = rsAccount.getLong(1);
|
||||
long domain_id = rsAccount.getLong(2);
|
||||
// 1. update cpu,memory for all accounts
|
||||
pstmt2 = conn.prepareStatement( "SELECT SUM(service_offering.cpu), SUM(service_offering.ram_size)" +
|
||||
" FROM `cloud`.`vm_instance`, `cloud`.`service_offering`" +
|
||||
" WHERE vm_instance.service_offering_id = service_offering.id AND vm_instance.account_id = ?" + " AND vm_instance.removed is NULL" +
|
||||
" AND vm_instance.vm_type='User' AND state not in ('Destroyed', 'Error', 'Expunging')");
|
||||
pstmt2.setLong(1, account_id);
|
||||
rsCount = pstmt2.executeQuery();
|
||||
if (rsCount.next()) {
|
||||
upgradeResourceCountforAccount(conn, account_id, domain_id, "cpu", rsCount.getLong(1));
|
||||
upgradeResourceCountforAccount(conn, account_id, domain_id, "memory", rsCount.getLong(2));
|
||||
} else {
|
||||
upgradeResourceCountforAccount(conn, account_id, domain_id, "cpu", 0L);
|
||||
upgradeResourceCountforAccount(conn, account_id, domain_id, "memory", 0L);
|
||||
}
|
||||
// 2. update primary_storage for all accounts
|
||||
pstmt3 = conn.prepareStatement("SELECT sum(size) FROM `cloud`.`volumes` WHERE account_id= ?" +
|
||||
" AND (path is not NULL OR state in ('Allocated')) AND removed is NULL" +
|
||||
" AND instance_id IN (SELECT id FROM `cloud`.`vm_instance` WHERE vm_type='User')");
|
||||
pstmt3.setLong(1, account_id);
|
||||
rsCount = pstmt3.executeQuery();
|
||||
if (rsCount.next()) {
|
||||
upgradeResourceCountforAccount(conn, account_id, domain_id, "primary_storage", rsCount.getLong(1));
|
||||
} else {
|
||||
upgradeResourceCountforAccount(conn, account_id, domain_id, "primary_storage", 0L);
|
||||
}
|
||||
// 3. update secondary_storage for all accounts
|
||||
long totalVolumesSize = 0;
|
||||
long totalSnapshotsSize = 0;
|
||||
long totalTemplatesSize = 0;
|
||||
pstmt4 = conn.prepareStatement("SELECT sum(size) FROM `cloud`.`volumes` WHERE account_id= ?" +
|
||||
" AND path is NULL AND state not in ('Allocated') AND removed is NULL");
|
||||
pstmt4.setLong(1, account_id);
|
||||
rsCount = pstmt4.executeQuery();
|
||||
if (rsCount.next()) {
|
||||
totalVolumesSize = rsCount.getLong(1);
|
||||
}
|
||||
pstmt4 = conn.prepareStatement("SELECT sum(size) FROM `cloud`.`snapshots` WHERE account_id= ? AND removed is NULL");
|
||||
pstmt4.setLong(1, account_id);
|
||||
rsCount = pstmt4.executeQuery();
|
||||
if (rsCount.next()) {
|
||||
totalSnapshotsSize = rsCount.getLong(1);
|
||||
}
|
||||
pstmt4 = conn.prepareStatement("SELECT sum(template_store_ref.size) FROM `cloud`.`template_store_ref`,`cloud`.`vm_template` WHERE account_id = ?" +
|
||||
" AND template_store_ref.template_id = vm_template.id AND download_state = 'DOWNLOADED' AND destroyed = false AND removed is NULL");
|
||||
pstmt4.setLong(1, account_id);
|
||||
rsCount = pstmt4.executeQuery();
|
||||
if (rsCount.next()) {
|
||||
totalTemplatesSize = rsCount.getLong(1);
|
||||
}
|
||||
upgradeResourceCountforAccount(conn, account_id, domain_id, "secondary_storage", totalVolumesSize + totalSnapshotsSize + totalTemplatesSize);
|
||||
}
|
||||
// 4. upgrade cpu,memory,primary_storage,secondary_storage for domains
|
||||
String resource_types[] = {"cpu","memory", "primary_storage", "secondary_storage"};
|
||||
pstmt5 = conn.prepareStatement("select id FROM `cloud`.`domain`");
|
||||
rsAccount = pstmt5.executeQuery();
|
||||
while (rsAccount.next()) {
|
||||
long domain_id = rsAccount.getLong(1);
|
||||
for(int count=0; count < resource_types.length; count++) {
|
||||
String resource_type = resource_types[count];
|
||||
upgradeResourceCountforDomain(conn, domain_id, resource_type, 0L); // reset value to 0 before statistics
|
||||
}
|
||||
}
|
||||
for(int count= 0; count < resource_types.length; count++) {
|
||||
String resource_type = resource_types[count];
|
||||
pstmt5 = conn.prepareStatement("select account.domain_id,sum(resource_count.count) from `cloud`.`account` left join `cloud`.`resource_count` on account.id=resource_count.account_id " +
|
||||
"where resource_count.type=? group by account.domain_id;");
|
||||
pstmt5.setString(1, resource_type);
|
||||
rsCount = pstmt5.executeQuery();
|
||||
while (rsCount.next()) {
|
||||
long domain_id = rsCount.getLong(1);
|
||||
long resource_count = rsCount.getLong(2);
|
||||
upgradeResourceCountforDomain(conn, domain_id, resource_type, resource_count);
|
||||
}
|
||||
}
|
||||
s_logger.debug("upgradeResourceCount finish");
|
||||
} catch (SQLException e) {
|
||||
throw new CloudRuntimeException("Unable to upgrade resource count (cpu,memory,primary_storage,secondary_storage) ", e);
|
||||
} finally {
|
||||
try {
|
||||
if (rs != null) {
|
||||
rs.close();
|
||||
}
|
||||
if (rsAccount != null) {
|
||||
rsAccount.close();
|
||||
}
|
||||
if (rsCount != null) {
|
||||
rsCount.close();
|
||||
}
|
||||
if (pstmt1 != null) {
|
||||
pstmt1.close();
|
||||
}
|
||||
if (pstmt2 != null) {
|
||||
pstmt2.close();
|
||||
}
|
||||
if (pstmt3 != null) {
|
||||
pstmt3.close();
|
||||
}
|
||||
if (pstmt4 != null) {
|
||||
pstmt4.close();
|
||||
}
|
||||
if (pstmt5 != null) {
|
||||
pstmt5.close();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void upgradeResourceCountforAccount(Connection conn, Long account_id, Long domain_id, String type, Long resource_count) throws SQLException {
|
||||
//update or insert into resource_count table.
|
||||
PreparedStatement pstmt = null;
|
||||
pstmt = conn.prepareStatement("INSERT INTO `cloud`.`resource_count` (account_id, type, count) VALUES (?,?,?) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), count=?");
|
||||
pstmt.setLong(1, account_id);
|
||||
pstmt.setString(2, type);
|
||||
pstmt.setLong(3, resource_count);
|
||||
pstmt.setLong(4, resource_count);
|
||||
pstmt.executeUpdate();
|
||||
pstmt.close();
|
||||
}
|
||||
|
||||
private static void upgradeResourceCountforDomain(Connection conn, Long domain_id, String type, Long resource_count) throws SQLException {
|
||||
//update or insert into resource_count table.
|
||||
PreparedStatement pstmt = null;
|
||||
pstmt = conn.prepareStatement("INSERT INTO `cloud`.`resource_count` (domain_id, type, count) VALUES (?,?,?) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), count=?");
|
||||
pstmt.setLong(1, domain_id);
|
||||
pstmt.setString(2, type);
|
||||
pstmt.setLong(3, resource_count);
|
||||
pstmt.setLong(4, resource_count);
|
||||
pstmt.executeUpdate();
|
||||
pstmt.close();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -431,7 +431,9 @@ public class
|
|||
int _createprivatetemplatefromsnapshotwait = NumbersUtil.parseInt(value,
|
||||
Integer.parseInt(Config.CreatePrivateTemplateFromSnapshotWait.getDefaultValue()));
|
||||
|
||||
boolean needCache = false;
|
||||
if (needCacheStorage(srcData, destData)) {
|
||||
needCache = true;
|
||||
SnapshotInfo snapshot = (SnapshotInfo) srcData;
|
||||
srcData = cacheSnapshotChain(snapshot);
|
||||
}
|
||||
|
|
@ -439,6 +441,11 @@ public class
|
|||
CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _createprivatetemplatefromsnapshotwait, _mgmtServer.getExecuteInSequence());
|
||||
EndPoint ep = selector.select(srcData, destData);
|
||||
Answer answer = ep.sendMessage(cmd);
|
||||
|
||||
// clean up snapshot copied to staging
|
||||
if (needCache && srcData != null) {
|
||||
cacheMgr.deleteCacheObject(srcData);
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,9 @@ public class DataMotionServiceImpl implements DataMotionService {
|
|||
|
||||
@Override
|
||||
public void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
|
||||
if (srcData.getDataStore() == null || destData.getDataStore() == null) {
|
||||
throw new CloudRuntimeException("can't find data store");
|
||||
}
|
||||
|
||||
if (srcData.getDataStore().getDriver().canCopy(srcData, destData)) {
|
||||
srcData.getDataStore().getDriver().copyAsync(srcData, destData, callback);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package org.apache.cloudstack.storage.snapshot;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.utils.db.DB;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.*;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
|
||||
|
|
@ -253,11 +254,23 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
|
|||
}
|
||||
|
||||
try {
|
||||
SnapshotResult result = snapshotSvr.takeSnapshot(snapshot);
|
||||
if (result.isFailed()) {
|
||||
s_logger.debug("Failed to take snapshot: " + result.getResult());
|
||||
throw new CloudRuntimeException(result.getResult());
|
||||
VolumeInfo volumeInfo = snapshot.getBaseVolume();
|
||||
volumeInfo.stateTransit(Volume.Event.SnapshotRequested);
|
||||
SnapshotResult result = null;
|
||||
try {
|
||||
result = snapshotSvr.takeSnapshot(snapshot);
|
||||
if (result.isFailed()) {
|
||||
s_logger.debug("Failed to take snapshot: " + result.getResult());
|
||||
throw new CloudRuntimeException(result.getResult());
|
||||
}
|
||||
} finally {
|
||||
if (result != null && result.isSuccess()) {
|
||||
volumeInfo.stateTransit(Volume.Event.OperationSucceeded);
|
||||
} else {
|
||||
volumeInfo.stateTransit(Volume.Event.OperationFailed);
|
||||
}
|
||||
}
|
||||
|
||||
snapshot = result.getSnashot();
|
||||
DataStore primaryStore = snapshot.getDataStore();
|
||||
|
||||
|
|
|
|||
|
|
@ -364,9 +364,13 @@ public class PrimaryDataStoreImpl implements PrimaryDataStore {
|
|||
return this.pdsv.getPodId();
|
||||
}
|
||||
|
||||
public Date getRemoved() {
|
||||
return this.pdsv.getRemoved();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInMaintenance() {
|
||||
return this.getStatus() == StoragePoolStatus.Maintenance ? true : false;
|
||||
return this.getStatus() == StoragePoolStatus.PrepareForMaintenance || this.getStatus() == StoragePoolStatus.Maintenance || this.getStatus() == StoragePoolStatus.ErrorInMaintenance || this.getRemoved() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
return false;
|
||||
}
|
||||
VolumeDataStoreVO volumeStore = _volumeStoreDao.findByVolume(volumeId);
|
||||
if (vol.getState() == State.Expunged && volumeStore == null) {
|
||||
if ((vol.getState() == State.Expunged || (vol.getPodId() == null && vol.getState() == State.Destroy)) && volumeStore == null) {
|
||||
// volume is expunged from primary, as well as on secondary
|
||||
return true;
|
||||
} else {
|
||||
|
|
@ -264,18 +264,23 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
|
||||
String volumePath = vol.getPath();
|
||||
Long poolId = vol.getPoolId();
|
||||
if (poolId == null || volumePath == null || volumePath.trim().isEmpty()) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Marking volume that was never created as destroyed: " + vol);
|
||||
if (poolId == null || volumePath == null || volumePath.trim().isEmpty() ) {
|
||||
// not created on primary store
|
||||
if (volumeStore == null) {
|
||||
// also not created on secondary store
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Marking volume that was never created as destroyed: " + vol);
|
||||
}
|
||||
volDao.remove(vol.getId());
|
||||
future.complete(result);
|
||||
return future;
|
||||
}
|
||||
volDao.remove(vol.getId());
|
||||
future.complete(result);
|
||||
return future;
|
||||
}
|
||||
VolumeObject vo = (VolumeObject) volume;
|
||||
|
||||
if (volume.getDataStore().getRole() == DataStoreRole.Image) {
|
||||
volume.processEvent(Event.DestroyRequested);
|
||||
// no need to change state in volumes table
|
||||
volume.processEventOnly(Event.DestroyRequested);
|
||||
} else if (volume.getDataStore().getRole() == DataStoreRole.Primary) {
|
||||
volume.processEvent(Event.ExpungeRequested);
|
||||
}
|
||||
|
|
@ -577,12 +582,12 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
@Override
|
||||
@DB
|
||||
public boolean destroyVolume(long volumeId) throws ConcurrentOperationException {
|
||||
|
||||
// mark volume entry in volumes table as destroy state
|
||||
VolumeInfo vol = volFactory.getVolume(volumeId);
|
||||
vol.processEvent(Event.DestroyRequested);
|
||||
vol.stateTransit(Volume.Event.DestroyRequested);
|
||||
snapshotMgr.deletePoliciesForVolume(volumeId);
|
||||
|
||||
vol.processEvent(Event.OperationSuccessed);
|
||||
vol.stateTransit(Volume.Event.OperationSucceeded);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1297,22 +1302,11 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
|
||||
@Override
|
||||
public SnapshotInfo takeSnapshot(VolumeInfo volume) {
|
||||
VolumeObject vol = (VolumeObject) volume;
|
||||
boolean result = vol.stateTransit(Volume.Event.SnapshotRequested);
|
||||
if (!result) {
|
||||
s_logger.debug("Failed to transit state");
|
||||
}
|
||||
SnapshotInfo snapshot = null;
|
||||
try {
|
||||
snapshot = snapshotMgr.takeSnapshot(volume);
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Take snapshot: " + volume.getId() + " failed", e);
|
||||
} finally {
|
||||
if (snapshot != null) {
|
||||
vol.stateTransit(Volume.Event.OperationSucceeded);
|
||||
} else {
|
||||
vol.stateTransit(Volume.Event.OperationFailed);
|
||||
}
|
||||
}
|
||||
|
||||
return snapshot;
|
||||
|
|
|
|||
|
|
@ -476,6 +476,13 @@ 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
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
SHORTNAME="cloud-agent"
|
||||
SHORTNAME="cloudstack-agent"
|
||||
PIDFILE=/var/run/"$SHORTNAME".pid
|
||||
LOCKFILE=/var/lock/subsys/"$SHORTNAME"
|
||||
PROGNAME="CloudStack Agent"
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
# Required-Stop: $local_fs
|
||||
# Should-Start:
|
||||
# Should-Stop:
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Start:
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Start up the cloud.com service
|
||||
# Short-Description: Start up the CloudStack cloud service
|
||||
### END INIT INFO
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
|
|
@ -74,7 +74,7 @@ _failure() {
|
|||
fi
|
||||
}
|
||||
RETVAL=$?
|
||||
CLOUD_COM_HOME="/usr/local/cloud"
|
||||
CLOUDSTACK_HOME="/usr/local/cloud"
|
||||
|
||||
# mkdir -p /var/log/vmops
|
||||
|
||||
|
|
@ -82,23 +82,23 @@ get_pids() {
|
|||
local i
|
||||
for i in $(ps -ef| grep java | grep -v grep | awk '{print $2}');
|
||||
do
|
||||
echo $(pwdx $i) | grep "$CLOUD_COM_HOME" | awk -F: '{print $1}';
|
||||
echo $(pwdx $i) | grep "$CLOUDSTACK_HOME" | awk -F: '{print $1}';
|
||||
done
|
||||
}
|
||||
|
||||
start() {
|
||||
local pid=$(get_pids)
|
||||
if [ "$pid" != "" ]; then
|
||||
echo "cloud.com sevice is already running, PID = $pid"
|
||||
echo "CloudStack cloud sevice is already running, PID = $pid"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo -n "Starting cloud.com service (type=$TYPE) "
|
||||
if [ -f $CLOUD_COM_HOME/systemvm/run.sh ];
|
||||
echo -n "Starting CloudStack cloud service (type=$TYPE) "
|
||||
if [ -f $CLOUDSTACK_HOME/systemvm/run.sh ];
|
||||
then
|
||||
if [ "$pid" == "" ]
|
||||
then
|
||||
(cd $CLOUD_COM_HOME/systemvm; nohup ./run.sh > /var/log/cloud/cloud.out 2>&1 & )
|
||||
(cd $CLOUDSTACK_HOME/systemvm; nohup ./run.sh > /var/log/cloud/cloud.out 2>&1 & )
|
||||
pid=$(get_pids)
|
||||
echo $pid > /var/run/cloud.pid
|
||||
fi
|
||||
|
|
@ -107,29 +107,29 @@ start() {
|
|||
_failure
|
||||
fi
|
||||
echo
|
||||
echo 'start' > $CLOUD_COM_HOME/systemvm/user_request
|
||||
echo 'start' > $CLOUDSTACK_HOME/systemvm/user_request
|
||||
}
|
||||
|
||||
stop() {
|
||||
local pid
|
||||
echo -n "Stopping cloud.com service (type=$TYPE): "
|
||||
echo -n "Stopping CloudStack cloud service (type=$TYPE): "
|
||||
for pid in $(get_pids)
|
||||
do
|
||||
kill $pid
|
||||
done
|
||||
_success
|
||||
echo
|
||||
echo 'stop' > $CLOUD_COM_HOME/systemvm/user_request
|
||||
echo 'stop' > $CLOUDSTACK_HOME/systemvm/user_request
|
||||
}
|
||||
|
||||
status() {
|
||||
local pids=$(get_pids)
|
||||
if [ "$pids" == "" ]
|
||||
then
|
||||
echo "cloud.com service is not running"
|
||||
echo "CloudStack cloud service is not running"
|
||||
return 1
|
||||
fi
|
||||
echo "cloud.com service (type=$TYPE) is running: process id: $pids"
|
||||
echo "CloudStack cloud service (type=$TYPE) is running: process id: $pids"
|
||||
return 0
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -848,7 +848,7 @@ setup_redundant_router() {
|
|||
crontab -l|grep "check_heartbeat.sh"
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
(crontab -l; echo "*/1 * * * * $rrouter_bin_path/check_heartbeat.sh 2>&1 > /dev/null") | crontab
|
||||
(crontab -l; echo -e "SHELL=/bin/bash\nPATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin\n*/1 * * * * $rrouter_bin_path/check_heartbeat.sh 2>&1 > /dev/null") | crontab
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ then
|
|||
lasttime=$(cat [RROUTER_BIN_PATH]/keepalived.ts2)
|
||||
thistime=$(cat [RROUTER_BIN_PATH]/keepalived.ts)
|
||||
diff=$(($thistime - $lasttime))
|
||||
if [ $diff -lt 30]
|
||||
if [ $diff -lt 30 ]
|
||||
then
|
||||
echo Keepalived process is dead! >> [RROUTER_LOG]
|
||||
service keepalived stop >> [RROUTER_LOG] 2>&1
|
||||
|
|
|
|||
|
|
@ -147,18 +147,7 @@ public class BridgeVifDriver extends VifDriverBase {
|
|||
}
|
||||
|
||||
private String setVnetBrName(String pifName, String vnetId) {
|
||||
String brName = null;
|
||||
if (bridgeNameSchema != null) {
|
||||
if (bridgeNameSchema.equalsIgnoreCase("3.0")) {
|
||||
brName = "cloudVirBr" + vnetId;
|
||||
} else if (bridgeNameSchema.equalsIgnoreCase("4.0")) {
|
||||
brName = "br" + pifName + "-"+ vnetId;
|
||||
}
|
||||
} else {
|
||||
brName = "br" + pifName + "-"+ vnetId;
|
||||
}
|
||||
|
||||
return brName;
|
||||
return "br" + pifName + "-"+ vnetId;
|
||||
}
|
||||
|
||||
private String createVlanBr(String vlanId, String nic)
|
||||
|
|
|
|||
|
|
@ -1367,7 +1367,7 @@ ServerResource {
|
|||
secondaryStorageUrl
|
||||
+ volumeDestPath);
|
||||
_storagePoolMgr.copyPhysicalDisk(volume,
|
||||
destVolumeName,secondaryStoragePool);
|
||||
destVolumeName,secondaryStoragePool, 0);
|
||||
return new CopyVolumeAnswer(cmd, true, null, null, volumeName);
|
||||
} else {
|
||||
volumePath = "/volumes/" + cmd.getVolumeId() + File.separator;
|
||||
|
|
@ -1377,7 +1377,7 @@ ServerResource {
|
|||
KVMPhysicalDisk volume = secondaryStoragePool
|
||||
.getPhysicalDisk(cmd.getVolumePath() + ".qcow2");
|
||||
_storagePoolMgr.copyPhysicalDisk(volume, volumeName,
|
||||
primaryPool);
|
||||
primaryPool, 0);
|
||||
return new CopyVolumeAnswer(cmd, true, null, null, volumeName);
|
||||
}
|
||||
} catch (CloudRuntimeException e) {
|
||||
|
|
@ -1463,7 +1463,7 @@ ServerResource {
|
|||
} else {
|
||||
BaseVol = primaryPool.getPhysicalDisk(cmd.getTemplateUrl());
|
||||
vol = _storagePoolMgr.createDiskFromTemplate(BaseVol, UUID
|
||||
.randomUUID().toString(), primaryPool);
|
||||
.randomUUID().toString(), primaryPool, 0);
|
||||
}
|
||||
if (vol == null) {
|
||||
return new Answer(cmd, false,
|
||||
|
|
@ -1524,7 +1524,7 @@ ServerResource {
|
|||
|
||||
/* Copy volume to primary storage */
|
||||
|
||||
KVMPhysicalDisk primaryVol = _storagePoolMgr.copyPhysicalDisk(templateVol, UUID.randomUUID().toString(), primaryPool);
|
||||
KVMPhysicalDisk primaryVol = _storagePoolMgr.copyPhysicalDisk(templateVol, UUID.randomUUID().toString(), primaryPool, 0);
|
||||
return primaryVol;
|
||||
} catch (CloudRuntimeException e) {
|
||||
s_logger.error("Failed to download template to primary storage",e);
|
||||
|
|
@ -2381,7 +2381,7 @@ ServerResource {
|
|||
primaryUuid);
|
||||
String volUuid = UUID.randomUUID().toString();
|
||||
KVMPhysicalDisk disk = _storagePoolMgr.copyPhysicalDisk(snapshot,
|
||||
volUuid, primaryPool);
|
||||
volUuid, primaryPool, 0);
|
||||
return new CreateVolumeFromSnapshotAnswer(cmd, true, "",
|
||||
disk.getName());
|
||||
} catch (CloudRuntimeException e) {
|
||||
|
|
@ -2532,7 +2532,7 @@ ServerResource {
|
|||
QemuImgFile destFile = new QemuImgFile(tmpltPath + "/" + cmd.getUniqueName() + ".qcow2");
|
||||
destFile.setFormat(PhysicalDiskFormat.QCOW2);
|
||||
|
||||
QemuImg q = new QemuImg();
|
||||
QemuImg q = new QemuImg(0);
|
||||
try {
|
||||
q.convert(srcFile, destFile);
|
||||
} catch (QemuImgException e) {
|
||||
|
|
@ -2635,7 +2635,7 @@ ServerResource {
|
|||
cmd.getPoolUuid());
|
||||
|
||||
KVMPhysicalDisk primaryVol = _storagePoolMgr.copyPhysicalDisk(
|
||||
tmplVol, UUID.randomUUID().toString(), primaryPool);
|
||||
tmplVol, UUID.randomUUID().toString(), primaryPool, 0);
|
||||
|
||||
return new PrimaryStorageDownloadAnswer(primaryVol.getName(),
|
||||
primaryVol.getSize());
|
||||
|
|
@ -2663,7 +2663,7 @@ ServerResource {
|
|||
|
||||
Map<String, TemplateProp> tInfo = new HashMap<String, TemplateProp>();
|
||||
ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd,
|
||||
storagepool.getCapacity(), storagepool.getUsed(), tInfo);
|
||||
storagepool.getCapacity(), storagepool.getAvailable(), tInfo);
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -206,25 +206,25 @@ public class KVMStoragePoolManager {
|
|||
}
|
||||
|
||||
public KVMPhysicalDisk createDiskFromTemplate(KVMPhysicalDisk template, String name,
|
||||
KVMStoragePool destPool) {
|
||||
KVMStoragePool destPool, int timeout) {
|
||||
StorageAdaptor adaptor = getStorageAdaptor(destPool.getType());
|
||||
|
||||
// LibvirtStorageAdaptor-specific statement
|
||||
if (destPool.getType() == StoragePoolType.RBD) {
|
||||
return adaptor.createDiskFromTemplate(template, name,
|
||||
PhysicalDiskFormat.RAW, template.getSize(), destPool);
|
||||
PhysicalDiskFormat.RAW, template.getSize(), destPool, timeout);
|
||||
} else if (destPool.getType() == StoragePoolType.CLVM) {
|
||||
return adaptor.createDiskFromTemplate(template, name,
|
||||
PhysicalDiskFormat.RAW, template.getSize(),
|
||||
destPool);
|
||||
destPool, timeout);
|
||||
} else if (template.getFormat() == PhysicalDiskFormat.DIR) {
|
||||
return adaptor.createDiskFromTemplate(template, name,
|
||||
PhysicalDiskFormat.DIR,
|
||||
template.getSize(), destPool);
|
||||
template.getSize(), destPool, timeout);
|
||||
} else {
|
||||
return adaptor.createDiskFromTemplate(template, name,
|
||||
PhysicalDiskFormat.QCOW2,
|
||||
template.getSize(), destPool);
|
||||
template.getSize(), destPool, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -237,9 +237,9 @@ public class KVMStoragePoolManager {
|
|||
}
|
||||
|
||||
public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name,
|
||||
KVMStoragePool destPool) {
|
||||
KVMStoragePool destPool, int timeout) {
|
||||
StorageAdaptor adaptor = getStorageAdaptor(destPool.getType());
|
||||
return adaptor.copyPhysicalDisk(disk, name, destPool);
|
||||
return adaptor.copyPhysicalDisk(disk, name, destPool, timeout);
|
||||
}
|
||||
|
||||
public KVMPhysicalDisk createDiskFromSnapshot(KVMPhysicalDisk snapshot,
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
primaryStore.getUuid());
|
||||
|
||||
KVMPhysicalDisk primaryVol = storagePoolMgr.copyPhysicalDisk(tmplVol, UUID.randomUUID().toString(),
|
||||
primaryPool);
|
||||
primaryPool, cmd.getWaitInMillSeconds());
|
||||
|
||||
|
||||
DataTO data = null;
|
||||
|
|
@ -232,7 +232,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
}
|
||||
|
||||
// this is much like PrimaryStorageDownloadCommand, but keeping it separate
|
||||
private KVMPhysicalDisk templateToPrimaryDownload(String templateUrl, KVMStoragePool primaryPool) {
|
||||
private KVMPhysicalDisk templateToPrimaryDownload(String templateUrl, KVMStoragePool primaryPool, int timeout) {
|
||||
int index = templateUrl.lastIndexOf("/");
|
||||
String mountpoint = templateUrl.substring(0, index);
|
||||
String templateName = null;
|
||||
|
|
@ -269,7 +269,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
/* Copy volume to primary storage */
|
||||
|
||||
KVMPhysicalDisk primaryVol = storagePoolMgr.copyPhysicalDisk(templateVol, UUID.randomUUID().toString(),
|
||||
primaryPool);
|
||||
primaryPool, timeout);
|
||||
return primaryVol;
|
||||
} catch (CloudRuntimeException e) {
|
||||
s_logger.error("Failed to download template to primary storage", e);
|
||||
|
|
@ -300,14 +300,14 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
|
||||
if (primaryPool.getType() == StoragePoolType.CLVM) {
|
||||
templatePath = ((NfsTO)imageStore).getUrl() + File.separator + templatePath;
|
||||
vol = templateToPrimaryDownload(templatePath, primaryPool);
|
||||
vol = templateToPrimaryDownload(templatePath, primaryPool, cmd.getWaitInMillSeconds());
|
||||
} else {
|
||||
if (templatePath.contains("/mnt")) {
|
||||
//upgrade issue, if the path contains path, need to extract the volume uuid from path
|
||||
templatePath = templatePath.substring(templatePath.lastIndexOf(File.separator) + 1);
|
||||
}
|
||||
BaseVol = storagePoolMgr.getPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), templatePath);
|
||||
vol = storagePoolMgr.createDiskFromTemplate(BaseVol, UUID.randomUUID().toString(), BaseVol.getPool());
|
||||
vol = storagePoolMgr.createDiskFromTemplate(BaseVol, UUID.randomUUID().toString(), BaseVol.getPool(), cmd.getWaitInMillSeconds());
|
||||
}
|
||||
if (vol == null) {
|
||||
return new CopyCmdAnswer(" Can't create storage volume on storage pool");
|
||||
|
|
@ -378,7 +378,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
.getPhysicalDisk(srcVolumeName);
|
||||
volume.setFormat(PhysicalDiskFormat.valueOf(srcFormat.toString()));
|
||||
KVMPhysicalDisk newDisk = storagePoolMgr.copyPhysicalDisk(volume, volumeName,
|
||||
primaryPool);
|
||||
primaryPool, cmd.getWaitInMillSeconds());
|
||||
VolumeObjectTO newVol = new VolumeObjectTO();
|
||||
newVol.setFormat(ImageFormat.valueOf(newDisk.getFormat().toString().toUpperCase()));
|
||||
newVol.setPath(volumeName);
|
||||
|
|
@ -425,7 +425,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
secondaryStoragePool = storagePoolMgr.getStoragePoolByURI(
|
||||
secondaryStorageUrl + File.separator + destVolumePath);
|
||||
storagePoolMgr.copyPhysicalDisk(volume,
|
||||
destVolumeName,secondaryStoragePool);
|
||||
destVolumeName,secondaryStoragePool, cmd.getWaitInMillSeconds());
|
||||
VolumeObjectTO newVol = new VolumeObjectTO();
|
||||
newVol.setPath(destVolumePath + File.separator + destVolumeName);
|
||||
newVol.setFormat(destFormat);
|
||||
|
|
@ -443,7 +443,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
public Answer createTemplateFromVolume(CopyCommand cmd) {
|
||||
DataTO srcData = cmd.getSrcTO();
|
||||
DataTO destData = cmd.getDestTO();
|
||||
int wait = cmd.getWait();
|
||||
int wait = cmd.getWaitInMillSeconds();
|
||||
TemplateObjectTO template = (TemplateObjectTO) destData;
|
||||
DataStoreTO imageStore = template.getDataStore();
|
||||
VolumeObjectTO volume = (VolumeObjectTO) srcData;
|
||||
|
|
@ -469,7 +469,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
String templateName = UUID.randomUUID().toString();
|
||||
|
||||
if (primary.getType() != StoragePoolType.RBD) {
|
||||
Script command = new Script(_createTmplPath, wait * 1000, s_logger);
|
||||
Script command = new Script(_createTmplPath, wait, s_logger);
|
||||
command.add("-f", disk.getPath());
|
||||
command.add("-t", tmpltPath);
|
||||
command.add("-n", templateName + ".qcow2");
|
||||
|
|
@ -490,7 +490,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
QemuImgFile destFile = new QemuImgFile(tmpltPath + "/" + templateName + ".qcow2");
|
||||
destFile.setFormat(PhysicalDiskFormat.QCOW2);
|
||||
|
||||
QemuImg q = new QemuImg();
|
||||
QemuImg q = new QemuImg(cmd.getWaitInMillSeconds());
|
||||
try {
|
||||
q.convert(srcFile, destFile);
|
||||
} catch (QemuImgException e) {
|
||||
|
|
@ -618,7 +618,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
SnapshotObjectTO snapshotOnCacheStore = (SnapshotObjectTO)answer.getNewData();
|
||||
snapshotOnCacheStore.setDataStore(cacheStore);
|
||||
((SnapshotObjectTO) destData).setDataStore(imageStore);
|
||||
CopyCommand newCpyCmd = new CopyCommand(snapshotOnCacheStore, destData, cmd.getWait(), cmd.executeInSequence());
|
||||
CopyCommand newCpyCmd = new CopyCommand(snapshotOnCacheStore, destData, cmd.getWaitInMillSeconds(), cmd.executeInSequence());
|
||||
return copyToObjectStore(newCpyCmd);
|
||||
}
|
||||
@Override
|
||||
|
|
@ -722,7 +722,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
return new CopyCmdAnswer(e.toString());
|
||||
}
|
||||
} else {
|
||||
Script command = new Script(_manageSnapshotPath, cmd.getWait() * 1000, s_logger);
|
||||
Script command = new Script(_manageSnapshotPath, cmd.getWaitInMillSeconds(), s_logger);
|
||||
command.add("-b", snapshotDisk.getPath());
|
||||
command.add("-n", snapshotName);
|
||||
command.add("-p", snapshotDestPath);
|
||||
|
|
@ -1184,7 +1184,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
String primaryUuid = pool.getUuid();
|
||||
KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(pool.getPoolType(), primaryUuid);
|
||||
String volUuid = UUID.randomUUID().toString();
|
||||
KVMPhysicalDisk disk = storagePoolMgr.copyPhysicalDisk(snapshotDisk, volUuid, primaryPool);
|
||||
KVMPhysicalDisk disk = storagePoolMgr.copyPhysicalDisk(snapshotDisk, volUuid, primaryPool, cmd.getWaitInMillSeconds());
|
||||
VolumeObjectTO newVol = new VolumeObjectTO();
|
||||
newVol.setPath(disk.getName());
|
||||
newVol.setSize(disk.getVirtualSize());
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
|
|||
// if error is that pool is mounted, try to handle it
|
||||
if (e.toString().contains("already mounted")) {
|
||||
s_logger.error("Attempting to unmount old mount libvirt is unaware of at "+targetPath);
|
||||
String result = Script.runSimpleBashScript("umount " + targetPath );
|
||||
String result = Script.runSimpleBashScript("umount -l " + targetPath );
|
||||
if (result == null) {
|
||||
s_logger.error("Succeeded in unmounting " + targetPath);
|
||||
try {
|
||||
|
|
@ -766,7 +766,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
|
|||
*/
|
||||
@Override
|
||||
public KVMPhysicalDisk createDiskFromTemplate(KVMPhysicalDisk template,
|
||||
String name, PhysicalDiskFormat format, long size, KVMStoragePool destPool) {
|
||||
String name, PhysicalDiskFormat format, long size, KVMStoragePool destPool, int timeout) {
|
||||
|
||||
String newUuid = UUID.randomUUID().toString();
|
||||
KVMStoragePool srcPool = template.getPool();
|
||||
|
|
@ -783,20 +783,20 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
|
|||
if (destPool.getType() != StoragePoolType.RBD) {
|
||||
disk = destPool.createPhysicalDisk(newUuid, format, template.getVirtualSize());
|
||||
if (template.getFormat() == PhysicalDiskFormat.TAR) {
|
||||
Script.runSimpleBashScript("tar -x -f " + template.getPath() + " -C " + disk.getPath());
|
||||
Script.runSimpleBashScript("tar -x -f " + template.getPath() + " -C " + disk.getPath(), timeout);
|
||||
} else if (template.getFormat() == PhysicalDiskFormat.DIR) {
|
||||
Script.runSimpleBashScript("mkdir -p " + disk.getPath());
|
||||
Script.runSimpleBashScript("chmod 755 " + disk.getPath());
|
||||
Script.runSimpleBashScript("cp -p -r " + template.getPath() + "/* " + disk.getPath());
|
||||
Script.runSimpleBashScript("cp -p -r " + template.getPath() + "/* " + disk.getPath(), timeout);
|
||||
} else if (format == PhysicalDiskFormat.QCOW2) {
|
||||
QemuImgFile backingFile = new QemuImgFile(template.getPath(), template.getFormat());
|
||||
QemuImgFile destFile = new QemuImgFile(disk.getPath());
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(timeout);
|
||||
qemu.create(destFile, backingFile);
|
||||
} else if (format == PhysicalDiskFormat.RAW) {
|
||||
QemuImgFile sourceFile = new QemuImgFile(template.getPath(), template.getFormat());
|
||||
QemuImgFile destFile = new QemuImgFile(disk.getPath(), PhysicalDiskFormat.RAW);
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(timeout);
|
||||
qemu.convert(sourceFile, destFile);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -806,7 +806,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
|
|||
disk.setSize(template.getVirtualSize());
|
||||
disk.setVirtualSize(disk.getSize());
|
||||
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(timeout);
|
||||
QemuImgFile srcFile;
|
||||
QemuImgFile destFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(destPool.getSourceHost(),
|
||||
destPool.getSourcePort(),
|
||||
|
|
@ -960,7 +960,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
|
|||
*/
|
||||
@Override
|
||||
public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name,
|
||||
KVMStoragePool destPool) {
|
||||
KVMStoragePool destPool, int timeout) {
|
||||
|
||||
/**
|
||||
With RBD you can't run qemu-img convert with an existing RBD image as destination
|
||||
|
|
@ -999,24 +999,27 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
|
|||
String destPath = newDisk.getPath();
|
||||
PhysicalDiskFormat destFormat = newDisk.getFormat();
|
||||
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(timeout);
|
||||
QemuImgFile srcFile = null;
|
||||
QemuImgFile destFile = null;
|
||||
|
||||
if ((srcPool.getType() != StoragePoolType.RBD) && (destPool.getType() != StoragePoolType.RBD)) {
|
||||
if (sourceFormat == PhysicalDiskFormat.TAR) {
|
||||
Script.runSimpleBashScript("tar -x -f " + sourcePath + " -C " + destPath);
|
||||
Script.runSimpleBashScript("tar -x -f " + sourcePath + " -C " + destPath, timeout);
|
||||
} else if (sourceFormat == PhysicalDiskFormat.DIR) {
|
||||
Script.runSimpleBashScript("mkdir -p " + destPath);
|
||||
Script.runSimpleBashScript("chmod 755 " + destPath);
|
||||
Script.runSimpleBashScript("cp -p -r " + sourcePath + "/* " + destPath);
|
||||
Script.runSimpleBashScript("cp -p -r " + sourcePath + "/* " + destPath, timeout);
|
||||
} else {
|
||||
srcFile = new QemuImgFile(sourcePath, sourceFormat);
|
||||
try {
|
||||
Map<String, String> info = qemu.info(srcFile);
|
||||
String backingFile = info.get(new String("backing_file"));
|
||||
if (sourceFormat.equals(destFormat) && backingFile == null) {
|
||||
Script.runSimpleBashScript("cp -f " + sourcePath + " " + destPath);
|
||||
String result = Script.runSimpleBashScript("cp -f " + sourcePath + " " + destPath, timeout);
|
||||
if (result != null) {
|
||||
throw new CloudRuntimeException("Failed to create disk: " + result);
|
||||
}
|
||||
} else {
|
||||
destFile = new QemuImgFile(destPath, destFormat);
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ public interface StorageAdaptor {
|
|||
|
||||
public KVMPhysicalDisk createDiskFromTemplate(KVMPhysicalDisk template,
|
||||
String name, PhysicalDiskFormat format, long size,
|
||||
KVMStoragePool destPool);
|
||||
KVMStoragePool destPool, int timeout);
|
||||
|
||||
public KVMPhysicalDisk createTemplateFromDisk(KVMPhysicalDisk disk,
|
||||
String name, PhysicalDiskFormat format, long size,
|
||||
|
|
@ -50,7 +50,7 @@ public interface StorageAdaptor {
|
|||
KVMStoragePool pool);
|
||||
|
||||
public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name,
|
||||
KVMStoragePool destPools);
|
||||
KVMStoragePool destPools, int timeout);
|
||||
|
||||
public KVMPhysicalDisk createDiskFromSnapshot(KVMPhysicalDisk snapshot,
|
||||
String snapshotName, String name, KVMStoragePool destPool);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ public class QemuImg {
|
|||
|
||||
/* The qemu-img binary. We expect this to be in $PATH */
|
||||
public String _qemuImgPath = "qemu-img";
|
||||
private int timeout;
|
||||
|
||||
/* Shouldn't we have KVMPhysicalDisk and LibvirtVMDef read this? */
|
||||
public static enum PhysicalDiskFormat {
|
||||
|
|
@ -46,8 +47,12 @@ public class QemuImg {
|
|||
}
|
||||
}
|
||||
|
||||
public QemuImg() {
|
||||
public QemuImg(int timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public void setTimeout(int timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -84,7 +89,7 @@ public class QemuImg {
|
|||
* @return void
|
||||
*/
|
||||
public void create(QemuImgFile file, QemuImgFile backingFile, Map<String, String> options) throws QemuImgException {
|
||||
Script s = new Script(_qemuImgPath);
|
||||
Script s = new Script(_qemuImgPath, timeout);
|
||||
s.add("create");
|
||||
|
||||
if (options != null && !options.isEmpty()) {
|
||||
|
|
@ -181,7 +186,7 @@ public class QemuImg {
|
|||
* @return void
|
||||
*/
|
||||
public void convert(QemuImgFile srcFile, QemuImgFile destFile, Map<String, String> options) throws QemuImgException {
|
||||
Script s = new Script(_qemuImgPath);
|
||||
Script s = new Script(_qemuImgPath, timeout);
|
||||
s.add("convert");
|
||||
s.add("-f");
|
||||
s.add(srcFile.getFormat().toString());
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ public class QemuImgTest {
|
|||
long size = 10995116277760l;
|
||||
QemuImgFile file = new QemuImgFile(filename, size, PhysicalDiskFormat.QCOW2);
|
||||
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(0);
|
||||
qemu.create(file);
|
||||
Map<String, String> info = qemu.info(file);
|
||||
|
||||
|
|
@ -69,7 +69,7 @@ public class QemuImgTest {
|
|||
|
||||
options.put("cluster_size", clusterSize);
|
||||
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(0);
|
||||
qemu.create(file, options);
|
||||
Map<String, String> info = qemu.info(file);
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ public class QemuImgTest {
|
|||
QemuImgFile file = new QemuImgFile(filename, startSize, PhysicalDiskFormat.QCOW2);
|
||||
|
||||
try {
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(0);
|
||||
qemu.create(file);
|
||||
qemu.resize(file, endSize);
|
||||
Map<String, String> info = qemu.info(file);
|
||||
|
|
@ -125,7 +125,7 @@ public class QemuImgTest {
|
|||
QemuImgFile file = new QemuImgFile(filename, startSize, PhysicalDiskFormat.RAW);
|
||||
|
||||
try {
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(0);
|
||||
qemu.create(file);
|
||||
qemu.resize(file, increment, true);
|
||||
Map<String, String> info = qemu.info(file);
|
||||
|
|
@ -153,7 +153,7 @@ public class QemuImgTest {
|
|||
QemuImgFile file = new QemuImgFile(filename, startSize, PhysicalDiskFormat.RAW);
|
||||
|
||||
try {
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(0);
|
||||
qemu.create(file);
|
||||
qemu.resize(file, increment, true);
|
||||
Map<String, String> info = qemu.info(file);
|
||||
|
|
@ -182,7 +182,7 @@ public class QemuImgTest {
|
|||
long endSize = -1;
|
||||
QemuImgFile file = new QemuImgFile(filename, startSize, PhysicalDiskFormat.QCOW2);
|
||||
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(0);
|
||||
try {
|
||||
qemu.create(file);
|
||||
qemu.resize(file, endSize);
|
||||
|
|
@ -199,7 +199,7 @@ public class QemuImgTest {
|
|||
long startSize = 20480;
|
||||
QemuImgFile file = new QemuImgFile(filename, 20480, PhysicalDiskFormat.QCOW2);
|
||||
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(0);
|
||||
qemu.create(file);
|
||||
qemu.resize(file, 0);
|
||||
|
||||
|
|
@ -216,7 +216,7 @@ public class QemuImgTest {
|
|||
QemuImgFile firstFile = new QemuImgFile(firstFileName, 20480, PhysicalDiskFormat.QCOW2);
|
||||
QemuImgFile secondFile = new QemuImgFile(secondFileName, PhysicalDiskFormat.QCOW2);
|
||||
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(0);
|
||||
qemu.create(firstFile);
|
||||
qemu.create(secondFile, firstFile);
|
||||
|
||||
|
|
@ -240,7 +240,7 @@ public class QemuImgTest {
|
|||
QemuImgFile srcFile = new QemuImgFile(srcFileName, srcSize);
|
||||
QemuImgFile destFile = new QemuImgFile(destFileName);
|
||||
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(0);
|
||||
qemu.create(srcFile);
|
||||
qemu.convert(srcFile, destFile);
|
||||
Map<String, String> info = qemu.info(destFile);
|
||||
|
|
@ -267,7 +267,7 @@ public class QemuImgTest {
|
|||
QemuImgFile srcFile = new QemuImgFile(srcFileName, srcSize, srcFormat);
|
||||
QemuImgFile destFile = new QemuImgFile(destFileName, destFormat);
|
||||
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(0);
|
||||
qemu.create(srcFile);
|
||||
qemu.convert(srcFile, destFile);
|
||||
|
||||
|
|
|
|||
|
|
@ -52,5 +52,10 @@
|
|||
<artifactId>cloud-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.inject</groupId>
|
||||
<artifactId>javax.inject</artifactId>
|
||||
<version>1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -67,6 +67,29 @@ public class UcsCommands {
|
|||
return cmd.toString();
|
||||
}
|
||||
|
||||
public static String disassociateProfileFromBlade(String cookie, String profileDn) {
|
||||
XmlObject cmd = new XmlObject("configConfMo");
|
||||
cmd.putElement("cookie", cookie);
|
||||
cmd.putElement("inHierarchical", "false")
|
||||
.putElement("inConfig", new XmlObject("inConfig")
|
||||
.putElement("lsServer", new XmlObject("lsServer")
|
||||
.putElement("dn", profileDn).putElement("lsBinding", new XmlObject("lsBinding").putElement("rn", "pn").putElement("status", "deleted"))
|
||||
)
|
||||
);
|
||||
|
||||
return cmd.dump();
|
||||
}
|
||||
|
||||
public static String deleteProfile(String cookie, String profileDn) {
|
||||
XmlObject cmd = new XmlObject("configConfMos");
|
||||
cmd.putElement("cookie", cookie);
|
||||
cmd.putElement("inHierarchical", "true")
|
||||
.putElement("inConfigs", new XmlObject("inConfigs").putElement("pair", new XmlObject("pair").putElement("key", profileDn)
|
||||
.putElement("lsServer", new XmlObject("lsServer").putElement("dn", profileDn).putElement("status", "deleted"))
|
||||
));
|
||||
return cmd.dump();
|
||||
}
|
||||
|
||||
public static String associateProfileToBlade(String cookie, String profileDn, String bladeDn) {
|
||||
XmlObject cmd = new XmlObject("configConfMos").putElement("cookie", cookie).putElement("inHierarchical", "true").putElement(
|
||||
"inConfigs", new XmlObject("inConfigs").putElement(
|
||||
|
|
@ -95,10 +118,10 @@ public class UcsCommands {
|
|||
.putElement("uuid", "")
|
||||
.putElement("vconProfileName", "")
|
||||
.putElement("lsBinding", new XmlObject("lsBinding")
|
||||
.putElement("pnDn", bladeDn)
|
||||
.putElement("restrictMigration", "no")
|
||||
.putElement("rn", "pn")
|
||||
)
|
||||
.putElement("pnDn", bladeDn)
|
||||
.putElement("restrictMigration", "no")
|
||||
.putElement("rn", "pn")
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
|
|
|||
7
plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsHttpClient.java
Normal file → Executable file
|
|
@ -19,6 +19,7 @@ package com.cloud.ucs.manager;
|
|||
|
||||
import org.apache.commons.httpclient.Header;
|
||||
import org.apache.commons.httpclient.HttpClient;
|
||||
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
|
||||
import org.apache.commons.httpclient.URI;
|
||||
import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory;
|
||||
import org.apache.commons.httpclient.methods.PostMethod;
|
||||
|
|
@ -28,10 +29,14 @@ import org.apache.commons.httpclient.protocol.Protocol;
|
|||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
public class UcsHttpClient {
|
||||
private static HttpClient client = new HttpClient();
|
||||
private static HttpClient client;
|
||||
private static Protocol ucsHttpsProtocol = new org.apache.commons.httpclient.protocol.Protocol("https", new EasySSLProtocolSocketFactory(), 443);
|
||||
private final String url;
|
||||
|
||||
static {
|
||||
client = new HttpClient();
|
||||
}
|
||||
|
||||
public UcsHttpClient(String ip) {
|
||||
url = String.format("http://%s/nuova", ip);
|
||||
Protocol.registerProtocol("https", ucsHttpsProtocol);
|
||||
|
|
|
|||
|
|
@ -42,4 +42,6 @@ public interface UcsManager extends Manager, PluggableService {
|
|||
ListResponse<UcsBladeResponse> listUcsBlades(ListUcsBladeCmd cmd);
|
||||
|
||||
void deleteUcsManager(Long id);
|
||||
|
||||
UcsBladeResponse disassociateProfile(Long bladeId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,17 +30,12 @@ import javax.ejb.Local;
|
|||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.cloudstack.api.AddUcsManagerCmd;
|
||||
import org.apache.cloudstack.api.AssociateUcsProfileToBladeCmd;
|
||||
import org.apache.cloudstack.api.ListUcsBladeCmd;
|
||||
import org.apache.cloudstack.api.ListUcsManagerCmd;
|
||||
import org.apache.cloudstack.api.ListUcsProfileCmd;
|
||||
import org.apache.cloudstack.api.*;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.api.response.UcsBladeResponse;
|
||||
import org.apache.cloudstack.api.response.UcsManagerResponse;
|
||||
import org.apache.cloudstack.api.response.UcsProfileResponse;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.cloudstack.api.DeleteUcsManagerCmd;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.configuration.Config;
|
||||
import com.cloud.configuration.dao.ConfigurationDao;
|
||||
|
|
@ -296,7 +291,14 @@ public class UcsManagerImpl implements UcsManager {
|
|||
UcsHttpClient client = new UcsHttpClient(mgrvo.getUrl());
|
||||
String res = client.call(cmd);
|
||||
List<UcsProfile> profiles = UcsProfile.fromXmlString(res);
|
||||
return profiles;
|
||||
List<UcsProfile> unassociated = new ArrayList<UcsProfile>();
|
||||
for (UcsProfile p : profiles) {
|
||||
if (isProfileAssociated(mgrvo.getId(), p.getDn())) {
|
||||
continue;
|
||||
}
|
||||
unassociated.add(p);
|
||||
}
|
||||
return unassociated;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -324,6 +326,7 @@ public class UcsManagerImpl implements UcsManager {
|
|||
return xo.get("outConfig.lsServer.dn");
|
||||
}
|
||||
|
||||
|
||||
private boolean isProfileAssociated(Long ucsMgrId, String dn) {
|
||||
UcsManagerVO mgrvo = ucsDao.findById(ucsMgrId);
|
||||
UcsHttpClient client = new UcsHttpClient(mgrvo.getUrl());
|
||||
|
|
@ -331,6 +334,17 @@ public class UcsManagerImpl implements UcsManager {
|
|||
String cmd = UcsCommands.configResolveDn(cookie, dn);
|
||||
String res = client.call(cmd);
|
||||
XmlObject xo = XmlObjectParser.parseFromString(res);
|
||||
|
||||
return xo.get("outConfig.lsServer.assocState").equals("associated");
|
||||
}
|
||||
|
||||
private boolean isBladeAssociated(Long ucsMgrId, String dn) {
|
||||
UcsManagerVO mgrvo = ucsDao.findById(ucsMgrId);
|
||||
UcsHttpClient client = new UcsHttpClient(mgrvo.getUrl());
|
||||
String cookie = getCookie(ucsMgrId);
|
||||
String cmd = UcsCommands.configResolveDn(cookie, dn);
|
||||
String res = client.call(cmd);
|
||||
XmlObject xo = XmlObjectParser.parseFromString(res);
|
||||
s_logger.debug(String.format("association response is %s", res));
|
||||
|
||||
if (xo.get("outConfig.computeBlade.association").equals("none")) {
|
||||
|
|
@ -361,9 +375,9 @@ public class UcsManagerImpl implements UcsManager {
|
|||
UcsHttpClient client = new UcsHttpClient(mgrvo.getUrl());
|
||||
String res = client.call(ucscmd);
|
||||
int count = 0;
|
||||
int timeout = 600;
|
||||
int timeout = 3600;
|
||||
while (count < timeout) {
|
||||
if (isProfileAssociated(mgrvo.getId(), bvo.getDn())) {
|
||||
if (isBladeAssociated(mgrvo.getId(), bvo.getDn())) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -504,6 +518,7 @@ public class UcsManagerImpl implements UcsManager {
|
|||
cmds.add(AddUcsManagerCmd.class);
|
||||
cmds.add(AssociateUcsProfileToBladeCmd.class);
|
||||
cmds.add(DeleteUcsManagerCmd.class);
|
||||
cmds.add(DisassociateUcsProfileCmd.class);
|
||||
return cmds;
|
||||
}
|
||||
|
||||
|
|
@ -517,4 +532,21 @@ public class UcsManagerImpl implements UcsManager {
|
|||
}
|
||||
ucsDao.remove(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UcsBladeResponse disassociateProfile(Long bladeId) {
|
||||
UcsBladeVO blade = bladeDao.findById(bladeId);
|
||||
UcsManagerVO mgrvo = ucsDao.findById(blade.getUcsManagerId());
|
||||
UcsHttpClient client = new UcsHttpClient(mgrvo.getUrl());
|
||||
String cookie = getCookie(mgrvo.getId());
|
||||
String cmd = UcsCommands.disassociateProfileFromBlade(cookie, blade.getProfileDn());
|
||||
client.call(cmd);
|
||||
cmd = UcsCommands.deleteProfile(cookie, blade.getProfileDn());
|
||||
client = new UcsHttpClient(mgrvo.getUrl());
|
||||
client.call(cmd);
|
||||
blade.setProfileDn(null);
|
||||
bladeDao.update(blade.getId(), blade);
|
||||
UcsBladeResponse rsp = bladeVOToResponse(blade);
|
||||
return rsp;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
package org.apache.cloudstack.api;
|
||||
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.*;
|
||||
import com.cloud.ucs.manager.UcsManager;
|
||||
import com.cloud.user.Account;
|
||||
import org.apache.cloudstack.api.response.SuccessResponse;
|
||||
import org.apache.cloudstack.api.response.UcsBladeResponse;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
* User: frank
|
||||
* Date: 9/13/13
|
||||
* Time: 6:23 PM
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
@APICommand(name="disassociateUcsProfileFromBlade", description="disassociate a profile from a blade", responseObject=UcsBladeResponse.class)
|
||||
public class DisassociateUcsProfileCmd extends BaseAsyncCmd {
|
||||
private static Logger logger = Logger.getLogger(DisassociateUcsProfileCmd.class);
|
||||
|
||||
@Inject
|
||||
private UcsManager mgr;
|
||||
|
||||
@Parameter(name=ApiConstants.UCS_BLADE_ID, type=CommandType.UUID, entityType=UcsBladeResponse.class, description="blade id", required=true)
|
||||
private Long bladeId;
|
||||
|
||||
@Override
|
||||
public String getEventType() {
|
||||
return EventTypes.EVENT_UCS_DISASSOCIATED_PROFILE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventDescription() {
|
||||
return "disassociate a profile from blade";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
|
||||
try {
|
||||
UcsBladeResponse rsp = mgr.disassociateProfile(bladeId);
|
||||
rsp.setResponseName(getCommandName());
|
||||
this.setResponseObject(rsp);
|
||||
} catch(Exception e) {
|
||||
logger.warn(e.getMessage(), e);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return "disassociateucsprofilefrombladeresponse";
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
}
|
||||
|
|
@ -374,6 +374,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
|
|||
CommandExecLogVO execLog = new CommandExecLogVO(cmdTarget.first().getId(), cmdTarget.second().getId(), cmd.getClass().getSimpleName(), 1);
|
||||
_cmdExecLogDao.persist(execLog);
|
||||
cmd.setContextParam("execid", String.valueOf(execLog.getId()));
|
||||
cmd.setContextParam("noderuninfo", String.format("%d-%d", _clusterMgr.getManagementNodeId(), _clusterMgr.getCurrentRunId()));
|
||||
|
||||
if(cmd instanceof BackupSnapshotCommand ||
|
||||
cmd instanceof CreatePrivateTemplateFromVolumeCommand ||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ public interface VmwareManager {
|
|||
|
||||
VmwareStorageManager getStorageManager();
|
||||
void gcLeftOverVMs(VmwareContext context);
|
||||
boolean needRecycle(String workerTag);
|
||||
|
||||
Pair<Integer, Integer> getAddiionalVncPortRange();
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ import com.cloud.agent.api.Command;
|
|||
import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.agent.api.StartupRoutingCommand;
|
||||
import com.cloud.cluster.ClusterManager;
|
||||
import com.cloud.cluster.ManagementServerHost;
|
||||
import com.cloud.cluster.dao.ManagementServerHostPeerDao;
|
||||
import com.cloud.configuration.Config;
|
||||
import com.cloud.configuration.dao.ConfigurationDao;
|
||||
import com.cloud.dc.ClusterDetailsDao;
|
||||
|
|
@ -154,6 +156,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
|||
@Inject VmwareDatacenterDao _vmwareDcDao;
|
||||
@Inject VmwareDatacenterZoneMapDao _vmwareDcZoneMapDao;
|
||||
@Inject LegacyZoneDao _legacyZoneDao;
|
||||
@Inject ManagementServerHostPeerDao _mshostPeerDao;
|
||||
|
||||
String _mountParent;
|
||||
StorageLayer _storage;
|
||||
|
|
@ -167,6 +170,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
|||
String _managemetPortGroupName;
|
||||
String _defaultSystemVmNicAdapterType = VirtualEthernetCardType.E1000.toString();
|
||||
String _recycleHungWorker = "false";
|
||||
long _hungWorkerTimeout = 7200000; // 2 hour
|
||||
int _additionalPortRangeStart;
|
||||
int _additionalPortRangeSize;
|
||||
int _routerExtraPublicNics = 2;
|
||||
|
|
@ -285,6 +289,10 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
|||
if(_recycleHungWorker == null || _recycleHungWorker.isEmpty()) {
|
||||
_recycleHungWorker = "false";
|
||||
}
|
||||
|
||||
value = _configDao.getValue(Config.VmwareHungWorkerTimeout.key());
|
||||
if(value != null)
|
||||
_hungWorkerTimeout = Long.parseLong(value) * 1000;
|
||||
|
||||
_rootDiskController = _configDao.getValue(Config.VmwareRootDiskControllerType.key());
|
||||
if(_rootDiskController == null || _rootDiskController.isEmpty()) {
|
||||
|
|
@ -528,11 +536,54 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
|||
return _storageMgr;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void gcLeftOverVMs(VmwareContext context) {
|
||||
VmwareCleanupMaid.gcLeftOverVMs(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needRecycle(String workerTag) {
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("Check to see if a worker VM with tag " + workerTag + " needs to be recycled");
|
||||
|
||||
if(workerTag == null || workerTag.isEmpty()) {
|
||||
s_logger.error("Invalid worker VM tag " + workerTag);
|
||||
return false;
|
||||
}
|
||||
|
||||
String tokens[] = workerTag.split("-");
|
||||
if(tokens.length != 3) {
|
||||
s_logger.error("Invalid worker VM tag " + workerTag);
|
||||
return false;
|
||||
}
|
||||
|
||||
long startTick = Long.parseLong(tokens[0]);
|
||||
long msid = Long.parseLong(tokens[1]);
|
||||
long runid = Long.parseLong(tokens[2]);
|
||||
|
||||
if(_mshostPeerDao.countStateSeenInPeers(msid, runid, ManagementServerHost.State.Down) > 0) {
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("Worker VM's owner management server node has been detected down from peer nodes, recycle it");
|
||||
return true;
|
||||
}
|
||||
|
||||
if(msid == _clusterMgr.getManagementNodeId() && runid != _clusterMgr.getCurrentRunId()) {
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("Worker VM's owner management server has changed runid, recycle it");
|
||||
return true;
|
||||
}
|
||||
|
||||
// disable time-out check until we have found out a VMware API that can check if
|
||||
// there are pending tasks on the subject VM
|
||||
/*
|
||||
if(System.currentTimeMillis() - startTick > _hungWorkerTimeout) {
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("Worker VM expired, seconds elapsed: " + (System.currentTimeMillis() - startTick) / 1000);
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareSecondaryStorageStore(String storageUrl) {
|
||||
|
|
|
|||
|
|
@ -329,14 +329,8 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
|||
dsMo = new DatastoreMO(hyperHost.getContext(), morDs);
|
||||
|
||||
workerVMName = hostService.getWorkerName(context, cmd, 0);
|
||||
|
||||
// attach a volume to dummay wrapper VM for taking snapshot and exporting the VM for backup
|
||||
if (!hyperHost.createBlankVm(workerVMName, null, 1, 512, 0, false, 4, 0, VirtualMachineGuestOsIdentifier.OTHER_GUEST.value(), morDs, false)) {
|
||||
String msg = "Unable to create worker VM to execute BackupSnapshotCommand";
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
vmMo = hyperHost.findVmOnHyperHost(workerVMName);
|
||||
vmMo = HypervisorHostHelper.createWorkerVM(hyperHost, dsMo, workerVMName);
|
||||
|
||||
if (vmMo == null) {
|
||||
throw new Exception("Failed to find the newly create or relocated VM. vmName: " + workerVMName);
|
||||
}
|
||||
|
|
@ -1059,28 +1053,8 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
|||
if (vmMo == null) {
|
||||
// create a dummy worker vm for attaching the volume
|
||||
DatastoreMO dsMo = new DatastoreMO(hyperHost.getContext(), morDs);
|
||||
//restrict VM name to 32 chars, (else snapshot descriptor file name will be truncated to 32 chars of vm name)
|
||||
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||
vmConfig.setName(workerVmName);
|
||||
vmConfig.setMemoryMB((long) 4);
|
||||
vmConfig.setNumCPUs(1);
|
||||
vmConfig.setGuestId(VirtualMachineGuestOsIdentifier.OTHER_GUEST.value());
|
||||
VirtualMachineFileInfo fileInfo = new VirtualMachineFileInfo();
|
||||
fileInfo.setVmPathName(String.format("[%s]", dsMo.getName()));
|
||||
vmConfig.setFiles(fileInfo);
|
||||
|
||||
// Scsi controller
|
||||
VirtualLsiLogicController scsiController = new VirtualLsiLogicController();
|
||||
scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
|
||||
scsiController.setBusNumber(0);
|
||||
scsiController.setKey(1);
|
||||
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||
scsiControllerSpec.setDevice(scsiController);
|
||||
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
vmConfig.getDeviceChange().add(scsiControllerSpec);
|
||||
|
||||
hyperHost.createVm(vmConfig);
|
||||
workerVm = hyperHost.findVmOnHyperHost(workerVmName);
|
||||
workerVm = HypervisorHostHelper.createWorkerVM(hyperHost, dsMo, workerVmName);
|
||||
|
||||
if (workerVm == null) {
|
||||
String msg = "Unable to create worker VM to execute CopyVolumeCommand";
|
||||
s_logger.error(msg);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import javax.inject.Inject;
|
|||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.cluster.ClusterManager;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareManager;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareClient;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
|
|
@ -34,9 +35,11 @@ public class VmwareContextFactory {
|
|||
|
||||
private static volatile int s_seq = 1;
|
||||
private static VmwareManager s_vmwareMgr;
|
||||
private static ClusterManager s_clusterMgr;
|
||||
private static VmwareContextPool s_pool;
|
||||
|
||||
@Inject VmwareManager _vmwareMgr;
|
||||
@Inject ClusterManager _clusterMgr;
|
||||
|
||||
static {
|
||||
// skip certificate check
|
||||
|
|
@ -47,6 +50,7 @@ public class VmwareContextFactory {
|
|||
@PostConstruct
|
||||
void init() {
|
||||
s_vmwareMgr = _vmwareMgr;
|
||||
s_clusterMgr = _clusterMgr;
|
||||
}
|
||||
|
||||
public static VmwareContext create(String vCenterAddress, String vCenterUserName, String vCenterPassword) throws Exception {
|
||||
|
|
@ -66,6 +70,7 @@ public class VmwareContextFactory {
|
|||
|
||||
context.registerStockObject("serviceconsole", s_vmwareMgr.getServiceConsolePortGroupName());
|
||||
context.registerStockObject("manageportgroup", s_vmwareMgr.getManagementPortGroupName());
|
||||
context.registerStockObject("noderuninfo", String.format("%d-%d", s_clusterMgr.getManagementNodeId(), s_clusterMgr.getCurrentRunId()));
|
||||
|
||||
context.setPoolInfo(s_pool, VmwareContextPool.composePoolKey(vCenterAddress, vCenterUserName));
|
||||
s_pool.registerOutstandingContext(context);
|
||||
|
|
@ -75,14 +80,22 @@ public class VmwareContextFactory {
|
|||
|
||||
public static VmwareContext getContext(String vCenterAddress, String vCenterUserName, String vCenterPassword) throws Exception {
|
||||
VmwareContext context = s_pool.getContext(vCenterAddress, vCenterUserName);
|
||||
if(context == null)
|
||||
if(context == null) {
|
||||
context = create(vCenterAddress, vCenterUserName, vCenterPassword);
|
||||
} else {
|
||||
if(!context.validate()) {
|
||||
s_logger.info("Validation of the context faild. dispose and create a new one");
|
||||
context.close();
|
||||
context = create(vCenterAddress, vCenterUserName, vCenterPassword);
|
||||
}
|
||||
}
|
||||
|
||||
if(context != null) {
|
||||
context.registerStockObject(VmwareManager.CONTEXT_STOCK_NAME, s_vmwareMgr);
|
||||
|
||||
context.registerStockObject("serviceconsole", s_vmwareMgr.getServiceConsolePortGroupName());
|
||||
context.registerStockObject("manageportgroup", s_vmwareMgr.getManagementPortGroupName());
|
||||
context.registerStockObject("noderuninfo", String.format("%d-%d", s_clusterMgr.getManagementNodeId(), s_clusterMgr.getCurrentRunId()));
|
||||
}
|
||||
|
||||
return context;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ import java.util.Collection;
|
|||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
|
@ -321,18 +320,14 @@ import com.vmware.vim25.VirtualDisk;
|
|||
import com.vmware.vim25.VirtualEthernetCard;
|
||||
import com.vmware.vim25.VirtualEthernetCardDistributedVirtualPortBackingInfo;
|
||||
import com.vmware.vim25.VirtualEthernetCardNetworkBackingInfo;
|
||||
import com.vmware.vim25.VirtualLsiLogicController;
|
||||
import com.vmware.vim25.VirtualMachineConfigSpec;
|
||||
import com.vmware.vim25.VirtualMachineFileInfo;
|
||||
import com.vmware.vim25.VirtualMachineGuestOsIdentifier;
|
||||
import com.vmware.vim25.VirtualMachinePowerState;
|
||||
import com.vmware.vim25.VirtualMachineRelocateSpec;
|
||||
import com.vmware.vim25.VirtualMachineRelocateSpecDiskLocator;
|
||||
import com.vmware.vim25.VirtualMachineRuntimeInfo;
|
||||
import com.vmware.vim25.VirtualSCSISharing;
|
||||
import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanIdSpec;
|
||||
|
||||
|
||||
public class VmwareResource implements StoragePoolResource, ServerResource, VmwareHostService {
|
||||
private static final Logger s_logger = Logger.getLogger(VmwareResource.class);
|
||||
|
||||
|
|
@ -368,7 +363,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
protected boolean _fullCloneFlag = false;
|
||||
protected boolean _instanceNameFlag = false;
|
||||
|
||||
|
||||
protected boolean _recycleHungWorker = false;
|
||||
protected DiskControllerType _rootDiskController = DiskControllerType.ide;
|
||||
|
||||
|
|
@ -2863,7 +2857,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
String[] diskChain = syncDiskChain(dcMo, vmMo, vmSpec,
|
||||
vol, matchingExistingDisk,
|
||||
dataStoresDetails);
|
||||
|
||||
if(controllerKey == scsiControllerKey && VmwareHelper.isReservedScsiDeviceNumber(scsiUnitNumber))
|
||||
scsiUnitNumber++;
|
||||
device = VmwareHelper.prepareDiskDevice(vmMo, null, controllerKey,
|
||||
diskChain,
|
||||
volumeDsDetails.first(),
|
||||
|
|
@ -4549,7 +4544,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
if (!dsMo.fileExists(volumeDatastorePath)) {
|
||||
String dummyVmName = getWorkerName(context, cmd, 0);
|
||||
|
||||
VirtualMachineMO vmMo = prepareVolumeHostDummyVm(hyperHost, dsMo, dummyVmName);
|
||||
VirtualMachineMO vmMo = HypervisorHostHelper.createWorkerVM(hyperHost, dsMo, dummyVmName);
|
||||
|
||||
if (vmMo == null) {
|
||||
throw new Exception("Unable to create a dummy VM for volume creation");
|
||||
|
|
@ -5704,7 +5699,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
VirtualMachineMO vmMo = null;
|
||||
|
||||
try {
|
||||
vmMo = prepareVolumeHostDummyVm(hyperHost, dsMo, dummyVmName);
|
||||
vmMo = HypervisorHostHelper.createWorkerVM(hyperHost, dsMo, dummyVmName);
|
||||
if (vmMo == null) {
|
||||
throw new Exception("Unable to create a dummy VM for volume creation");
|
||||
}
|
||||
|
|
@ -5761,7 +5756,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumeUuid);
|
||||
String dummyVmName = getWorkerName(context, cmd, 0);
|
||||
try {
|
||||
vmMo = prepareVolumeHostDummyVm(hyperHost, dsMo, dummyVmName);
|
||||
vmMo = HypervisorHostHelper.createWorkerVM(hyperHost, dsMo, dummyVmName);
|
||||
if (vmMo == null) {
|
||||
throw new Exception("Unable to create a dummy VM for volume creation");
|
||||
}
|
||||
|
|
@ -5796,34 +5791,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
return (int)(bytes / (1024L * 1024L));
|
||||
}
|
||||
|
||||
protected VirtualMachineMO prepareVolumeHostDummyVm(VmwareHypervisorHost hyperHost, DatastoreMO dsMo, String vmName) throws Exception {
|
||||
assert (hyperHost != null);
|
||||
|
||||
VirtualMachineMO vmMo = null;
|
||||
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||
vmConfig.setName(vmName);
|
||||
vmConfig.setMemoryMB((long) 4); // vmware request minimum of 4 MB
|
||||
vmConfig.setNumCPUs(1);
|
||||
vmConfig.setGuestId(VirtualMachineGuestOsIdentifier.OTHER_GUEST.value());
|
||||
VirtualMachineFileInfo fileInfo = new VirtualMachineFileInfo();
|
||||
fileInfo.setVmPathName(String.format("[%s]", dsMo.getName()));
|
||||
vmConfig.setFiles(fileInfo);
|
||||
|
||||
// Scsi controller
|
||||
VirtualLsiLogicController scsiController = new VirtualLsiLogicController();
|
||||
scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
|
||||
scsiController.setBusNumber(0);
|
||||
scsiController.setKey(1);
|
||||
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||
scsiControllerSpec.setDevice(scsiController);
|
||||
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
|
||||
vmConfig.getDeviceChange().add(scsiControllerSpec );
|
||||
hyperHost.createVm(vmConfig);
|
||||
vmMo = hyperHost.findVmOnHyperHost(vmName);
|
||||
return vmMo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnected() {
|
||||
}
|
||||
|
|
@ -5850,70 +5817,53 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
if(hyperHost.isHyperHostConnected()) {
|
||||
mgr.gcLeftOverVMs(context);
|
||||
|
||||
if(_recycleHungWorker) {
|
||||
s_logger.info("Scan hung worker VM to recycle");
|
||||
|
||||
int key = ((HostMO)hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_VM_INTERNAL_NAME);
|
||||
if(key == 0) {
|
||||
s_logger.warn("Custom field " + CustomFieldConstants.CLOUD_VM_INTERNAL_NAME + " is not registered ?!");
|
||||
}
|
||||
String instanceNameCustomField = "value[" + key + "]";
|
||||
|
||||
// GC worker that has been running for too long
|
||||
ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost(
|
||||
new String[] {"name", "config.template", "runtime.powerState", "runtime.bootTime", instanceNameCustomField });
|
||||
if(ocs != null) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
List<DynamicProperty> props = oc.getPropSet();
|
||||
if(props != null) {
|
||||
String vmName = null;
|
||||
String internalName = null;
|
||||
boolean template = false;
|
||||
VirtualMachinePowerState powerState = VirtualMachinePowerState.POWERED_OFF;
|
||||
GregorianCalendar bootTime = null;
|
||||
|
||||
for(DynamicProperty prop : props) {
|
||||
if (prop.getName().equals("name"))
|
||||
vmName = prop.getVal().toString();
|
||||
else if(prop.getName().startsWith("value[")) {
|
||||
if(prop.getVal() != null)
|
||||
internalName = ((CustomFieldStringValue)prop.getVal()).getValue();
|
||||
}
|
||||
else if(prop.getName().equals("config.template"))
|
||||
template = (Boolean)prop.getVal();
|
||||
else if(prop.getName().equals("runtime.powerState"))
|
||||
powerState = (VirtualMachinePowerState)prop.getVal();
|
||||
else if(prop.getName().equals("runtime.bootTime"))
|
||||
bootTime = (GregorianCalendar)prop.getVal();
|
||||
}
|
||||
|
||||
VirtualMachineMO vmMo = new VirtualMachineMO(hyperHost.getContext(), oc.getObj());
|
||||
String name = null;
|
||||
if (internalName != null) {
|
||||
name = internalName;
|
||||
} else {
|
||||
name = vmName;
|
||||
}
|
||||
|
||||
if(!template && name.matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")) {
|
||||
boolean recycle = false;
|
||||
|
||||
// recycle stopped worker VM and VM that has been running for too long (hard-coded 10 hours for now)
|
||||
if(powerState == VirtualMachinePowerState.POWERED_OFF)
|
||||
recycle = true;
|
||||
else if(bootTime != null && (new Date().getTime() - bootTime.getTimeInMillis() > 10*3600*1000))
|
||||
recycle = true;
|
||||
|
||||
if(recycle) {
|
||||
s_logger.info("Recycle pending worker VM: " + name);
|
||||
|
||||
vmMo.powerOff();
|
||||
vmMo.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
s_logger.info("Scan hung worker VM to recycle");
|
||||
|
||||
int workerKey = ((HostMO)hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_WORKER);
|
||||
int workerTagKey = ((HostMO)hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_WORKER_TAG);
|
||||
String workerPropName = String.format("value[%d]", workerKey);
|
||||
String workerTagPropName = String.format("value[%d]", workerTagKey);
|
||||
|
||||
// GC worker that has been running for too long
|
||||
ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost(
|
||||
new String[] {"name", "config.template", workerPropName, workerTagPropName,
|
||||
});
|
||||
if(ocs != null) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
List<DynamicProperty> props = oc.getPropSet();
|
||||
if(props != null) {
|
||||
boolean template = false;
|
||||
boolean isWorker = false;
|
||||
String workerTag = null;
|
||||
|
||||
for(DynamicProperty prop : props) {
|
||||
if(prop.getName().equals("config.template")) {
|
||||
template = (Boolean)prop.getVal();
|
||||
} else if(prop.getName().equals(workerPropName)) {
|
||||
CustomFieldStringValue val = (CustomFieldStringValue)prop.getVal();
|
||||
if(val != null && val.getValue() != null && val.getValue().equalsIgnoreCase("true"))
|
||||
isWorker = true;
|
||||
}
|
||||
else if(prop.getName().equals(workerTagPropName)) {
|
||||
CustomFieldStringValue val = (CustomFieldStringValue)prop.getVal();
|
||||
workerTag = val.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
VirtualMachineMO vmMo = new VirtualMachineMO(hyperHost.getContext(), oc.getObj());
|
||||
if(!template && isWorker) {
|
||||
boolean recycle = false;
|
||||
recycle = mgr.needRecycle(workerTag);
|
||||
|
||||
if(recycle) {
|
||||
s_logger.info("Recycle pending worker VM: " + vmMo.getName());
|
||||
|
||||
vmMo.powerOff();
|
||||
vmMo.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s_logger.error("Host is no longer connected.");
|
||||
|
|
@ -6694,6 +6644,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
cfmMo.ensureCustomFieldDef("VirtualMachine", CustomFieldConstants.CLOUD_UUID);
|
||||
cfmMo.ensureCustomFieldDef("VirtualMachine", CustomFieldConstants.CLOUD_NIC_MASK);
|
||||
cfmMo.ensureCustomFieldDef("VirtualMachine", CustomFieldConstants.CLOUD_VM_INTERNAL_NAME);
|
||||
cfmMo.ensureCustomFieldDef("VirtualMachine", CustomFieldConstants.CLOUD_WORKER);
|
||||
cfmMo.ensureCustomFieldDef("VirtualMachine", CustomFieldConstants.CLOUD_WORKER_TAG);
|
||||
|
||||
VmwareHypervisorHost hostMo = this.getHyperHost(context);
|
||||
_hostName = hostMo.getHyperHostName();
|
||||
|
|
|
|||
|
|
@ -16,11 +16,15 @@
|
|||
// under the License.
|
||||
package com.cloud.storage.resource;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareClient;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContextPool;
|
||||
|
||||
public class VmwareSecondaryStorageContextFactory {
|
||||
private static final Logger s_logger = Logger.getLogger(VmwareSecondaryStorageContextFactory.class);
|
||||
|
||||
private static volatile int s_seq = 1;
|
||||
|
||||
private static VmwareContextPool s_pool;
|
||||
|
|
@ -51,6 +55,12 @@ public class VmwareSecondaryStorageContextFactory {
|
|||
VmwareContext context = s_pool.getContext(vCenterAddress, vCenterUserName);
|
||||
if(context == null) {
|
||||
context = create(vCenterAddress, vCenterUserName, vCenterPassword);
|
||||
} else {
|
||||
if(!context.validate()) {
|
||||
s_logger.info("Validation of the context faild. dispose and create a new one");
|
||||
context.close();
|
||||
context = create(vCenterAddress, vCenterUserName, vCenterPassword);
|
||||
}
|
||||
}
|
||||
|
||||
if(context != null) {
|
||||
|
|
|
|||
|
|
@ -218,6 +218,7 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe
|
|||
if (context != null) {
|
||||
context.registerStockObject("serviceconsole", cmd.getContextParam("serviceconsole"));
|
||||
context.registerStockObject("manageportgroup", cmd.getContextParam("manageportgroup"));
|
||||
context.registerStockObject("noderuninfo", cmd.getContextParam("noderuninfo"));
|
||||
}
|
||||
currentContext.set(context);
|
||||
return context;
|
||||
|
|
|
|||
|
|
@ -173,7 +173,9 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
|||
}
|
||||
|
||||
if(vmMo.createSnapshot("cloud.template.base", "Base snapshot", false, false)) {
|
||||
vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_UUID, templateUuid);
|
||||
// the same template may be deployed with multiple copies at per-datastore per-host basis,
|
||||
// save the original template name from CloudStack DB as the UUID to associate them.
|
||||
vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_UUID, templateName);
|
||||
vmMo.markAsTemplate();
|
||||
} else {
|
||||
vmMo.destroy();
|
||||
|
|
@ -658,15 +660,10 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
|||
}
|
||||
|
||||
// 4 MB is the minimum requirement for VM memory in VMware
|
||||
vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(),
|
||||
Pair<VirtualMachineMO, String[]> cloneResult = vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(),
|
||||
VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first()));
|
||||
clonedVm = vmMo.getRunningHost().findVmOnHyperHost(workerVmName);
|
||||
if(clonedVm == null) {
|
||||
String msg = "Unable to create dummy VM to export volume. volume path: " + volumePath;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
clonedVm = cloneResult.first();
|
||||
|
||||
clonedVm.exportVm(secondaryMountPoint + "/" + installPath, templateUniqueName, true, false);
|
||||
|
||||
long physicalSize = new File(installFullPath + "/" + templateUniqueName + ".ova").length();
|
||||
|
|
@ -982,17 +979,12 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
|||
}
|
||||
|
||||
// 4 MB is the minimum requirement for VM memory in VMware
|
||||
String disks[] = vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(),
|
||||
VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first()));
|
||||
clonedVm = vmMo.getRunningHost().findVmOnHyperHost(workerVmName);
|
||||
if(clonedVm == null) {
|
||||
String msg = "Unable to create dummy VM to export volume. volume path: " + volumePath;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
Pair<VirtualMachineMO, String[]> cloneResult = vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(),
|
||||
VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first()));
|
||||
clonedVm = cloneResult.first();
|
||||
String disks[] = cloneResult.second();
|
||||
|
||||
clonedVm.exportVm(exportPath, exportName, false, false);
|
||||
|
||||
return new Pair<String, String[]>(volumeDeviceInfo.second(), disks);
|
||||
} finally {
|
||||
if(clonedVm != null) {
|
||||
|
|
|
|||
|
|
@ -102,7 +102,15 @@ public class VmwareStorageSubsystemCommandHandler extends StorageSubsystemComman
|
|||
TemplateObjectTO template = (TemplateObjectTO)answer.getNewData();
|
||||
template.setDataStore(srcDataStore);
|
||||
CopyCommand newCmd = new CopyCommand(template, destData, cmd.getWait(), cmd.executeInSequence());
|
||||
return storageResource.defaultAction(newCmd);
|
||||
Answer result = storageResource.defaultAction(newCmd);
|
||||
//clean up template data on staging area
|
||||
try {
|
||||
DeleteCommand deleteCommand = new DeleteCommand(template);
|
||||
storageResource.defaultAction(deleteCommand);
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Failed to clean up staging area:", e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
needDelegation = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
|||
|
||||
import com.cloud.agent.AgentManager;
|
||||
import com.cloud.cluster.ClusterManager;
|
||||
import com.cloud.cluster.dao.ManagementServerHostPeerDao;
|
||||
import com.cloud.configuration.dao.ConfigurationDao;
|
||||
import com.cloud.dc.ClusterDetailsDao;
|
||||
import com.cloud.dc.ClusterDetailsVO;
|
||||
|
|
@ -377,6 +378,11 @@ public class VmwareDatacenterApiUnitTest {
|
|||
return Mockito.mock(LegacyZoneDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ManagementServerHostPeerDao managementServerHostPeerDao() {
|
||||
return Mockito.mock(ManagementServerHostPeerDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ConfigurationDao configurationDao() {
|
||||
return Mockito.mock(ConfigurationDao.class);
|
||||
|
|
|
|||
|
|
@ -1819,37 +1819,19 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
protected MaintainAnswer execute(MaintainCommand cmd) {
|
||||
Connection conn = getConnection();
|
||||
try {
|
||||
Pool pool = Pool.getByUuid(conn, _host.pool);
|
||||
Pool.Record poolr = pool.getRecord(conn);
|
||||
|
||||
Host.Record hostr = poolr.master.getRecord(conn);
|
||||
if (!_host.uuid.equals(hostr.uuid)) {
|
||||
s_logger.debug("Not the master node so just return ok: " + _host.ip);
|
||||
return new MaintainAnswer(cmd);
|
||||
}
|
||||
Map<Host, Host.Record> hostMap = Host.getAllRecords(conn);
|
||||
if (hostMap.size() == 1) {
|
||||
s_logger.debug("There is the last host in pool " + poolr.uuid );
|
||||
return new MaintainAnswer(cmd);
|
||||
}
|
||||
Host newMaster = null;
|
||||
Host.Record newMasterRecord = null;
|
||||
for (Map.Entry<Host, Host.Record> entry : hostMap.entrySet()) {
|
||||
if (!_host.uuid.equals(entry.getValue().uuid)) {
|
||||
newMaster = entry.getKey();
|
||||
newMasterRecord = entry.getValue();
|
||||
s_logger.debug("New master for the XenPool is " + newMasterRecord.uuid + " : " + newMasterRecord.address);
|
||||
try {
|
||||
_connPool.switchMaster(_host.ip, _host.pool, conn, newMaster, _username, _password, _wait);
|
||||
return new MaintainAnswer(cmd, "New Master is " + newMasterRecord.address);
|
||||
} catch (XenAPIException e) {
|
||||
s_logger.warn("Unable to switch the new master to " + newMasterRecord.uuid + ": " + newMasterRecord.address + " Trying again...");
|
||||
} catch (XmlRpcException e) {
|
||||
s_logger.warn("Unable to switch the new master to " + newMasterRecord.uuid + ": " + newMasterRecord.address + " Trying again...");
|
||||
}
|
||||
|
||||
Host host = Host.getByUuid(conn, _host.uuid);
|
||||
// remove all tags cloud stack
|
||||
Host.Record hr = host.getRecord(conn);
|
||||
Iterator<String> it = hr.tags.iterator();
|
||||
while (it.hasNext()) {
|
||||
String tag = it.next();
|
||||
if (tag.contains("cloud")) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
return new MaintainAnswer(cmd, false, "Unable to find an appropriate host to set as the new master");
|
||||
host.setTags(conn, hr.tags);
|
||||
return new MaintainAnswer(cmd);
|
||||
} catch (XenAPIException e) {
|
||||
s_logger.warn("Unable to put server in maintainence mode", e);
|
||||
return new MaintainAnswer(cmd, false, e.getMessage());
|
||||
|
|
@ -4814,6 +4796,12 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
}
|
||||
}
|
||||
|
||||
protected void plugDom0Vif(Connection conn, VIF dom0Vif) throws XmlRpcException, XenAPIException {
|
||||
if (dom0Vif != null) {
|
||||
dom0Vif.plug(conn);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupLinkLocalNetwork(Connection conn) {
|
||||
try {
|
||||
Network.Record rec = new Network.Record();
|
||||
|
|
@ -4868,11 +4856,11 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
vifr.network = linkLocal;
|
||||
vifr.lockingMode = Types.VifLockingMode.NETWORK_DEFAULT;
|
||||
dom0vif = VIF.create(conn, vifr);
|
||||
dom0vif.plug(conn);
|
||||
plugDom0Vif(conn, dom0vif);
|
||||
} else {
|
||||
s_logger.debug("already have a vif on dom0 for link local network");
|
||||
if (!dom0vif.getCurrentlyAttached(conn)) {
|
||||
dom0vif.plug(conn);
|
||||
plugDom0Vif(conn, dom0vif);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7788,37 +7776,58 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
Connection conn = getConnection();
|
||||
String hostuuid = cmd.getHostuuid();
|
||||
try {
|
||||
Map<Host, Host.Record> hostrs = Host.getAllRecords(conn);
|
||||
boolean found = false;
|
||||
for( Host.Record hr : hostrs.values() ) {
|
||||
if( hr.uuid.equals(hostuuid)) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if( ! found) {
|
||||
Host host = Host.getByUuid(conn, hostuuid);
|
||||
if( isRefNull(host) ) {
|
||||
s_logger.debug("host " + hostuuid + " has already been ejected from pool " + _host.pool);
|
||||
return new Answer(cmd);
|
||||
}
|
||||
|
||||
Pool pool = Pool.getAll(conn).iterator().next();
|
||||
Pool.Record poolr = pool.getRecord(conn);
|
||||
|
||||
Host.Record masterRec = poolr.master.getRecord(conn);
|
||||
if (hostuuid.equals(masterRec.uuid)) {
|
||||
s_logger.debug("This is last host to eject, so don't need to eject: " + hostuuid);
|
||||
return new Answer(cmd);
|
||||
}
|
||||
|
||||
Host host = Host.getByUuid(conn, hostuuid);
|
||||
// remove all tags cloud stack add before eject
|
||||
Host.Record hr = host.getRecord(conn);
|
||||
Iterator<String> it = hr.tags.iterator();
|
||||
while (it.hasNext()) {
|
||||
String tag = it.next();
|
||||
if (tag.startsWith("vmops-version-")) {
|
||||
if (tag.contains("cloud")) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
host.setTags(conn, hr.tags);
|
||||
Pool pool = Pool.getByUuid(conn, _host.pool);
|
||||
Pool.Record poolr = pool.getRecord(conn);
|
||||
|
||||
Host.Record hostr = poolr.master.getRecord(conn);
|
||||
if (_host.uuid.equals(hostr.uuid)) {
|
||||
boolean mastermigrated = false;
|
||||
Map<Host, Host.Record> hostMap = Host.getAllRecords(conn);
|
||||
if (hostMap.size() != 1) {
|
||||
Host newMaster = null;
|
||||
Host.Record newMasterRecord = null;
|
||||
for (Map.Entry<Host, Host.Record> entry : hostMap.entrySet()) {
|
||||
if (_host.uuid.equals(entry.getValue().uuid)) {
|
||||
continue;
|
||||
}
|
||||
newMaster = entry.getKey();
|
||||
newMasterRecord = entry.getValue();
|
||||
s_logger.debug("New master for the XenPool is " + newMasterRecord.uuid + " : " + newMasterRecord.address);
|
||||
try {
|
||||
_connPool.switchMaster(_host.ip, _host.pool, conn, newMaster, _username, _password, _wait);
|
||||
mastermigrated = true;
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
s_logger.warn("Unable to switch the new master to " + newMasterRecord.uuid + ": " + newMasterRecord.address + " due to " + e.toString());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s_logger.debug("This is last host to eject, so don't need to eject: " + hostuuid);
|
||||
return new Answer(cmd);
|
||||
}
|
||||
if ( !mastermigrated ) {
|
||||
String msg = "this host is master, and cannot designate a new master";
|
||||
s_logger.debug(msg);
|
||||
return new Answer(cmd, false, msg);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// eject from pool
|
||||
try {
|
||||
Pool.eject(conn, host);
|
||||
|
|
@ -7832,12 +7841,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
host.destroy(conn);
|
||||
}
|
||||
return new Answer(cmd);
|
||||
} catch (XenAPIException e) {
|
||||
String msg = "XenAPIException Unable to destroy host " + _host.uuid + " in xenserver database due to " + e.toString();
|
||||
s_logger.warn(msg, e);
|
||||
return new Answer(cmd, false, msg);
|
||||
} catch (Exception e) {
|
||||
String msg = "Exception Unable to destroy host " + _host.uuid + " in xenserver database due to " + e.getMessage();
|
||||
String msg = "Exception Unable to destroy host " + _host.uuid + " in xenserver database due to " + e.toString();
|
||||
s_logger.warn(msg, e);
|
||||
return new Answer(cmd, false, msg);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,6 +160,7 @@ public class XenServer56FP1Resource extends XenServer56Resource {
|
|||
VM template = templates.iterator().next();
|
||||
|
||||
VM.Record vmr = template.getRecord(conn);
|
||||
vmr.platform.remove("device_id");
|
||||
vmr.affinity = host;
|
||||
vmr.otherConfig.remove("disks");
|
||||
vmr.otherConfig.remove("default_template");
|
||||
|
|
|
|||
|
|
@ -18,14 +18,9 @@ package com.cloud.hypervisor.xen.resource;
|
|||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.xmlrpc.XmlRpcException;
|
||||
|
||||
|
|
@ -37,21 +32,14 @@ import com.cloud.agent.api.FenceAnswer;
|
|||
import com.cloud.agent.api.FenceCommand;
|
||||
import com.cloud.agent.api.NetworkUsageAnswer;
|
||||
import com.cloud.agent.api.NetworkUsageCommand;
|
||||
import com.cloud.agent.api.PoolEjectCommand;
|
||||
import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.resource.ServerResource;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.script.Script;
|
||||
import com.xensource.xenapi.Bond;
|
||||
import com.xensource.xenapi.Connection;
|
||||
import com.xensource.xenapi.Host;
|
||||
import com.xensource.xenapi.Network;
|
||||
import com.xensource.xenapi.PBD;
|
||||
import com.xensource.xenapi.PIF;
|
||||
import com.xensource.xenapi.SR;
|
||||
import com.xensource.xenapi.Types;
|
||||
import com.xensource.xenapi.Types.IpConfigurationMode;
|
||||
import com.xensource.xenapi.Types.XenAPIException;
|
||||
import com.xensource.xenapi.VLAN;
|
||||
|
|
@ -65,8 +53,6 @@ public class XenServer56Resource extends CitrixResourceBase {
|
|||
public Answer executeRequest(Command cmd) {
|
||||
if (cmd instanceof FenceCommand) {
|
||||
return execute((FenceCommand) cmd);
|
||||
} else if (cmd instanceof PoolEjectCommand) {
|
||||
return execute((PoolEjectCommand) cmd);
|
||||
} else if (cmd instanceof NetworkUsageCommand) {
|
||||
return execute((NetworkUsageCommand) cmd);
|
||||
} else {
|
||||
|
|
@ -226,36 +212,6 @@ public class XenServer56Resource extends CitrixResourceBase {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Answer execute(PoolEjectCommand cmd) {
|
||||
Connection conn = getConnection();
|
||||
String hostuuid = cmd.getHostuuid();
|
||||
try {
|
||||
Host host = Host.getByUuid(conn, hostuuid);
|
||||
// remove all tags cloud stack add before eject
|
||||
Host.Record hr = host.getRecord(conn);
|
||||
Iterator<String> it = hr.tags.iterator();
|
||||
while (it.hasNext()) {
|
||||
String tag = it.next();
|
||||
if (tag.contains("cloud-heartbeat-")) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
return super.execute(cmd);
|
||||
|
||||
} catch (XenAPIException e) {
|
||||
String msg = "Unable to eject host " + _host.uuid + " due to " + e.toString();
|
||||
s_logger.warn(msg, e);
|
||||
return new Answer(cmd, false, msg);
|
||||
} catch (Exception e) {
|
||||
s_logger.warn("Unable to eject host " + _host.uuid, e);
|
||||
String msg = "Unable to eject host " + _host.uuid + " due to " + e.getMessage();
|
||||
s_logger.warn(msg, e);
|
||||
return new Answer(cmd, false, msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected FenceAnswer execute(FenceCommand cmd) {
|
||||
Connection conn = getConnection();
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ package com.cloud.hypervisor.xen.resource;
|
|||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
|
@ -28,35 +28,37 @@ import javax.ejb.Local;
|
|||
|
||||
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.xmlrpc.XmlRpcException;
|
||||
|
||||
import com.cloud.resource.ServerResource;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.script.Script;
|
||||
import com.cloud.vm.VirtualMachine.State;
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.storage.MigrateVolumeAnswer;
|
||||
import com.cloud.agent.api.storage.MigrateVolumeCommand;
|
||||
import com.cloud.agent.api.MigrateWithStorageAnswer;
|
||||
import com.cloud.agent.api.MigrateWithStorageCommand;
|
||||
import com.cloud.agent.api.MigrateWithStorageCompleteAnswer;
|
||||
import com.cloud.agent.api.MigrateWithStorageCompleteCommand;
|
||||
import com.cloud.agent.api.MigrateWithStorageReceiveAnswer;
|
||||
import com.cloud.agent.api.MigrateWithStorageReceiveCommand;
|
||||
import com.cloud.agent.api.MigrateWithStorageSendAnswer;
|
||||
import com.cloud.agent.api.MigrateWithStorageSendCommand;
|
||||
import com.cloud.agent.api.MigrateWithStorageCompleteAnswer;
|
||||
import com.cloud.agent.api.MigrateWithStorageCompleteCommand;
|
||||
import com.cloud.agent.api.to.StorageFilerTO;
|
||||
import com.cloud.network.Networks.TrafficType;
|
||||
import com.cloud.agent.api.storage.MigrateVolumeAnswer;
|
||||
import com.cloud.agent.api.storage.MigrateVolumeCommand;
|
||||
import com.cloud.agent.api.to.DiskTO;
|
||||
import com.cloud.agent.api.to.NicTO;
|
||||
import com.cloud.agent.api.to.StorageFilerTO;
|
||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||
import com.cloud.agent.api.to.VolumeTO;
|
||||
import com.cloud.agent.api.to.NicTO;
|
||||
import com.cloud.network.Networks.TrafficType;
|
||||
import com.cloud.resource.ServerResource;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.script.Script;
|
||||
import com.cloud.vm.VirtualMachine.State;
|
||||
import com.xensource.xenapi.Connection;
|
||||
import com.xensource.xenapi.Host;
|
||||
import com.xensource.xenapi.Network;
|
||||
import com.xensource.xenapi.SR;
|
||||
import com.xensource.xenapi.Task;
|
||||
import com.xensource.xenapi.Types;
|
||||
import com.xensource.xenapi.Types.XenAPIException;
|
||||
import com.xensource.xenapi.VBD;
|
||||
import com.xensource.xenapi.VDI;
|
||||
import com.xensource.xenapi.VIF;
|
||||
|
|
@ -447,4 +449,8 @@ public class XenServer610Resource extends XenServer56FP1Resource {
|
|||
return dynamicMinRam;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void plugDom0Vif(Connection conn, VIF dom0Vif) throws XmlRpcException, XenAPIException {
|
||||
// do nothing. In xenserver 6.1 and beyond this step isn't needed.
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -388,7 +388,8 @@ class nfsConfig(serviceCfgBase):
|
|||
return True
|
||||
|
||||
cfo = configFileOps("/etc/nfsmount.conf")
|
||||
cfo.addEntry("AC", "False")
|
||||
cfo.addEntry("Ac", "False")
|
||||
cfo.addEntry("actimeo", "0")
|
||||
cfo.save()
|
||||
|
||||
self.syscfg.svo.enableService("rpcbind")
|
||||
|
|
|
|||
|
|
@ -1072,12 +1072,12 @@ def network_rules_for_rebooted_vm(session, vmName):
|
|||
|
||||
#change antispoof rule in vmchain
|
||||
try:
|
||||
delcmd = "iptables-save | grep '\-A " + vmchain_default + "' | grep physdev-in | sed 's/-A/-D/'"
|
||||
delcmd2 = "iptables-save | grep '\-A " + vmchain_default + "' | grep physdev-out | sed 's/-A/-D/'"
|
||||
inscmd = "iptables-save | grep '\-A " + vmchain_default + "' | grep physdev-in | grep vif | sed -r 's/vif[0-9]+.0/" + vif + "/' | sed 's/-A/-I/'"
|
||||
inscmd2 = "iptables-save| grep '\-A " + vmchain_default + "' | grep physdev-in | grep tap | sed -r 's/tap[0-9]+.0/" + tap + "/' | sed 's/-A/-I/'"
|
||||
inscmd3 = "iptables-save | grep '\-A " + vmchain_default + "' | grep physdev-out | grep vif | sed -r 's/vif[0-9]+.0/" + vif + "/' | sed 's/-A/-I/'"
|
||||
inscmd4 = "iptables-save| grep '\-A " + vmchain_default + "' | grep physdev-out | grep tap | sed -r 's/tap[0-9]+.0/" + tap + "/' | sed 's/-A/-I/'"
|
||||
delcmd = "iptables-save | grep '\-A " + vmchain_default + "' | grep physdev-in | sed 's/!--set/! --set/' | sed 's/-A/-D/'"
|
||||
delcmd2 = "iptables-save | grep '\-A " + vmchain_default + "' | grep physdev-out | sed 's/!--set/! --set/'| sed 's/-A/-D/'"
|
||||
inscmd = "iptables-save | grep '\-A " + vmchain_default + "' | grep physdev-in | grep vif | sed -r 's/vif[0-9]+.0/" + vif + "/' | sed 's/!--set/! --set/'"
|
||||
inscmd2 = "iptables-save| grep '\-A " + vmchain_default + "' | grep physdev-in | grep tap | sed -r 's/tap[0-9]+.0/" + tap + "/' | sed 's/!--set/! --set/'"
|
||||
inscmd3 = "iptables-save | grep '\-A " + vmchain_default + "' | grep physdev-out | grep vif | sed -r 's/vif[0-9]+.0/" + vif + "/' | sed 's/!--set/! --set/'"
|
||||
inscmd4 = "iptables-save| grep '\-A " + vmchain_default + "' | grep physdev-out | grep tap | sed -r 's/tap[0-9]+.0/" + tap + "/' | sed 's/!--set/! --set/'"
|
||||
|
||||
ipts = []
|
||||
for cmd in [delcmd, delcmd2, inscmd, inscmd2, inscmd3, inscmd4]:
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ def default_network_rules_systemvm(vm_name, localbrname):
|
|||
if bridge != localbrname:
|
||||
if not addFWFramework(bridge):
|
||||
return False
|
||||
brfw = "BF-" + bridge
|
||||
brfw = getBrfw(bridge)
|
||||
vifs = getVifsForBridge(vm_name, bridge)
|
||||
for vif in vifs:
|
||||
try:
|
||||
|
|
@ -356,7 +356,7 @@ def default_network_rules(vm_name, vm_id, vm_ip, vm_mac, vif, brname, sec_ips):
|
|||
return False
|
||||
|
||||
vmName = vm_name
|
||||
brfw = "BF-" + brname
|
||||
brfw = getBrfw(brname)
|
||||
domID = getvmId(vm_name)
|
||||
delete_rules_for_vm_in_bridge_firewall_chain(vmName)
|
||||
vmchain = vm_name
|
||||
|
|
@ -549,7 +549,7 @@ def network_rules_for_rebooted_vm(vmName):
|
|||
if brName is None or brName is "":
|
||||
brName = "cloudbr0"
|
||||
else:
|
||||
brName = re.sub("^BF-", "", brName)
|
||||
brName = execute("iptables-save |grep physdev-is-bridged |grep FORWARD |grep BF |grep '\-o' |awk '{print $4}' | head -1").strip()
|
||||
|
||||
if 1 in [ vm_name.startswith(c) for c in ['r-', 's-', 'v-'] ]:
|
||||
|
||||
|
|
@ -562,8 +562,8 @@ def network_rules_for_rebooted_vm(vmName):
|
|||
vifs = getVifs(vmName)
|
||||
logging.debug(vifs, brName)
|
||||
for v in vifs:
|
||||
execute("iptables -A " + "BF-" + brName + "-IN " + " -m physdev --physdev-is-bridged --physdev-in " + v + " -j "+ vmchain_default)
|
||||
execute("iptables -A " + "BF-" + brName + "-OUT " + " -m physdev --physdev-is-bridged --physdev-out " + v + " -j "+ vmchain_default)
|
||||
execute("iptables -A " + getBrfw(brName) + "-IN " + " -m physdev --physdev-is-bridged --physdev-in " + v + " -j "+ vmchain_default)
|
||||
execute("iptables -A " + getBrfw(brName) + "-OUT " + " -m physdev --physdev-is-bridged --physdev-out " + v + " -j "+ vmchain_default)
|
||||
|
||||
#change antispoof rule in vmchain
|
||||
try:
|
||||
|
|
@ -871,6 +871,13 @@ def getBridges(vmName):
|
|||
def getvmId(vmName):
|
||||
cmd = "virsh list |grep " + vmName + " | awk '{print $1}'"
|
||||
return bash("-c", cmd).stdout.strip()
|
||||
|
||||
def getBrfw(brname):
|
||||
cmd = "iptables-save |grep physdev-is-bridged |grep FORWARD |grep BF |grep '\-o' | grep -w " + brname + "|awk '{print $9}' | head -1"
|
||||
brfwname = bash("-c", cmd).stdout.strip()
|
||||
if brfwname == "":
|
||||
brfwname = "BF-" + brname
|
||||
return brfwname
|
||||
|
||||
def addFWFramework(brname):
|
||||
try:
|
||||
|
|
@ -885,7 +892,7 @@ def addFWFramework(brname):
|
|||
logging.debug("failed to turn on bridge netfilter")
|
||||
return False
|
||||
|
||||
brfw = "BF-" + brname
|
||||
brfw = getBrfw(brname)
|
||||
try:
|
||||
execute("iptables -L " + brfw)
|
||||
except:
|
||||
|
|
|
|||
|
|
@ -1376,7 +1376,10 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl
|
|||
public boolean tapLoadingAgents(Long hostId, TapAgentsAction action) {
|
||||
synchronized (_loadingAgents) {
|
||||
if (action == TapAgentsAction.Add) {
|
||||
_loadingAgents.add(hostId);
|
||||
if (_loadingAgents.contains(hostId))
|
||||
return false;
|
||||
else
|
||||
_loadingAgents.add(hostId);
|
||||
} else if (action == TapAgentsAction.Del) {
|
||||
_loadingAgents.remove(hostId);
|
||||
} else if (action == TapAgentsAction.Contains) {
|
||||
|
|
|
|||
|
|
@ -1144,6 +1144,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
|
|||
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
|
||||
ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
|
||||
ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
|
||||
ssc.addOr("networkName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
|
||||
|
||||
sc.addAnd("instanceName", SearchCriteria.Op.SC, ssc);
|
||||
}
|
||||
|
|
@ -1571,7 +1572,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
|
|||
}
|
||||
|
||||
if (haHosts != null && haTag != null && !haTag.isEmpty()) {
|
||||
sc.setJoinParameters("hostTagSearch", "tag", haTag);
|
||||
sc.setParameters("tag", haTag);
|
||||
}
|
||||
|
||||
// search host details by ids
|
||||
|
|
@ -2508,7 +2509,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
|
|||
sdc.addOr("accountId", SearchCriteria.Op.EQ, account.getId());
|
||||
sdc.addOr("accountId", SearchCriteria.Op.NULL);
|
||||
|
||||
sc.addAnd("account", SearchCriteria.Op.SC, sdc);
|
||||
sc.addAnd("accountId", SearchCriteria.Op.SC, sdc);
|
||||
}
|
||||
|
||||
} else if (account.getType() == Account.ACCOUNT_TYPE_NORMAL) {
|
||||
|
|
@ -2537,7 +2538,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
|
|||
SearchCriteria<DataCenterJoinVO> sdc = _dcJoinDao.createSearchCriteria();
|
||||
sdc.addOr("domainId", SearchCriteria.Op.IN, domainIds.toArray());
|
||||
sdc.addOr("domainId", SearchCriteria.Op.NULL);
|
||||
sc.addAnd("domain", SearchCriteria.Op.SC, sdc);
|
||||
sc.addAnd("domainId", SearchCriteria.Op.SC, sdc);
|
||||
|
||||
// remove disabled zones
|
||||
sc.addAnd("allocationState", SearchCriteria.Op.NEQ, Grouping.AllocationState.Disabled);
|
||||
|
|
@ -2548,7 +2549,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
|
|||
sdc2.addOr("accountId", SearchCriteria.Op.EQ, account.getId());
|
||||
sdc2.addOr("accountId", SearchCriteria.Op.NULL);
|
||||
|
||||
sc.addAnd("account", SearchCriteria.Op.SC, sdc2);
|
||||
sc.addAnd("accountId", SearchCriteria.Op.SC, sdc2);
|
||||
|
||||
// remove Dedicated zones not dedicated to this domainId or
|
||||
// subdomainId
|
||||
|
|
@ -2588,7 +2589,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
|
|||
SearchCriteria<DataCenterJoinVO> sdc = _dcJoinDao.createSearchCriteria();
|
||||
sdc.addOr("domainId", SearchCriteria.Op.IN, domainIds.toArray());
|
||||
sdc.addOr("domainId", SearchCriteria.Op.NULL);
|
||||
sc.addAnd("domain", SearchCriteria.Op.SC, sdc);
|
||||
sc.addAnd("domainId", SearchCriteria.Op.SC, sdc);
|
||||
|
||||
// remove disabled zones
|
||||
sc.addAnd("allocationState", SearchCriteria.Op.NEQ, Grouping.AllocationState.Disabled);
|
||||
|
|
@ -2617,7 +2618,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
|
|||
if (dcIds.size() == 0) {
|
||||
return new Pair<List<DataCenterJoinVO>, Integer>(new ArrayList<DataCenterJoinVO>(), 0);
|
||||
} else {
|
||||
sc.addAnd("idIn", SearchCriteria.Op.IN, dcIds.toArray());
|
||||
sc.addAnd("id", SearchCriteria.Op.IN, dcIds.toArray());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ import com.cloud.uservm.UserVm;
|
|||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.vm.UserVmVO;
|
||||
import com.cloud.vm.VmStats;
|
||||
import com.cloud.vm.VirtualMachine.State;
|
||||
|
||||
|
|
@ -166,35 +165,25 @@ public class UserVmJoinDaoImpl extends GenericDaoBase<UserVmJoinVO, Long> implem
|
|||
userVmResponse.setKeyPairName(userVm.getKeypairName());
|
||||
|
||||
if (details.contains(VMDetails.all) || details.contains(VMDetails.stats)) {
|
||||
DecimalFormat decimalFormat = new DecimalFormat("#.##");
|
||||
// stats calculation
|
||||
String cpuUsed = null;
|
||||
VmStats vmStats = ApiDBUtils.getVmStatistics(userVm.getId());
|
||||
if (vmStats != null) {
|
||||
float cpuUtil = (float) vmStats.getCPUUtilization();
|
||||
cpuUsed = decimalFormat.format(cpuUtil) + "%";
|
||||
userVmResponse.setCpuUsed(cpuUsed);
|
||||
userVmResponse.setCpuUsed(new DecimalFormat("#.##").format(vmStats.getCPUUtilization()) + "%");
|
||||
|
||||
Double networkKbRead = Double.valueOf(vmStats.getNetworkReadKBs());
|
||||
userVmResponse.setNetworkKbsRead(networkKbRead.longValue());
|
||||
userVmResponse.setNetworkKbsRead((long) vmStats.getNetworkReadKBs());
|
||||
|
||||
Double networkKbWrite = Double.valueOf(vmStats.getNetworkWriteKBs());
|
||||
userVmResponse.setNetworkKbsWrite(networkKbWrite.longValue());
|
||||
userVmResponse.setNetworkKbsWrite((long) vmStats.getNetworkWriteKBs());
|
||||
|
||||
if ((userVm.getHypervisorType() != null)
|
||||
&& (userVm.getHypervisorType().equals(HypervisorType.KVM)
|
||||
|| userVm.getHypervisorType().equals(HypervisorType.XenServer))) { // support KVM and XenServer only util 2013.06.25
|
||||
Double diskKbsRead = Double.valueOf(vmStats.getDiskReadKBs());
|
||||
userVmResponse.setDiskKbsRead(diskKbsRead.longValue());
|
||||
userVmResponse.setDiskKbsRead((long) vmStats.getDiskReadKBs());
|
||||
|
||||
Double diskKbsWrite = Double.valueOf(vmStats.getDiskWriteKBs());
|
||||
userVmResponse.setDiskKbsWrite(diskKbsWrite.longValue());
|
||||
userVmResponse.setDiskKbsWrite((long) vmStats.getDiskWriteKBs());
|
||||
|
||||
Double diskIORead = Double.valueOf(vmStats.getDiskReadIOs());
|
||||
userVmResponse.setDiskIORead(diskIORead.longValue());
|
||||
userVmResponse.setDiskIORead((long) vmStats.getDiskReadIOs());
|
||||
|
||||
Double diskIOWrite = Double.valueOf(vmStats.getDiskWriteIOs());
|
||||
userVmResponse.setDiskIOWrite(diskIOWrite.longValue());
|
||||
userVmResponse.setDiskIOWrite((long) vmStats.getDiskWriteIOs());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -298,6 +298,7 @@ public enum Config {
|
|||
VmwareRootDiskControllerType("Advanced", ManagementServer.class, String.class, "vmware.root.disk.controller", "ide", "Specify the default disk controller for root volumes, valid values are scsi, ide", null),
|
||||
VmwareSystemVmNicDeviceType("Advanced", ManagementServer.class, String.class, "vmware.systemvm.nic.device.type", "E1000", "Specify the default network device type for system VMs, valid values are E1000, PCNet32, Vmxnet2, Vmxnet3", null),
|
||||
VmwareRecycleHungWorker("Advanced", ManagementServer.class, Boolean.class, "vmware.recycle.hung.wokervm", "false", "Specify whether or not to recycle hung worker VMs", null),
|
||||
VmwareHungWorkerTimeout("Advanced", ManagementServer.class, Long.class, "vmware.hung.wokervm.timeout", "7200", "Worker VM timeout in seconds", null),
|
||||
VmwareEnableNestedVirtualization("Advanced", ManagementServer.class, Boolean.class, "vmware.nested.virtualization", "false", "When set to true this will enable nested virtualization when this is supported by the hypervisor", null),
|
||||
|
||||
// Midonet
|
||||
|
|
|
|||
|
|
@ -4001,7 +4001,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
}
|
||||
validateLoadBalancerServiceCapabilities(lbServiceCapabilityMap);
|
||||
|
||||
if (!serviceProviderMap.containsKey(Service.Lb) && lbServiceCapabilityMap != null && !lbServiceCapabilityMap.isEmpty()) {
|
||||
if (lbServiceCapabilityMap != null && !lbServiceCapabilityMap.isEmpty()) {
|
||||
maxconn = cmd.getMaxconnections();
|
||||
if (maxconn == null) {
|
||||
maxconn=Integer.parseInt(_configDao.getValue(Config.NetworkLBHaproxyMaxConn.key()));
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
|
|||
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
|
||||
import org.apache.cloudstack.engine.cloud.entity.api.db.VMReservationVO;
|
||||
import org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMReservationDao;
|
||||
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.StoragePoolAllocator;
|
||||
import org.apache.cloudstack.framework.messagebus.MessageBus;
|
||||
|
|
@ -78,6 +79,7 @@ import com.cloud.org.Cluster;
|
|||
import com.cloud.org.Grouping;
|
||||
import com.cloud.resource.ResourceState;
|
||||
import com.cloud.storage.DiskOfferingVO;
|
||||
import com.cloud.storage.ScopeType;
|
||||
import com.cloud.storage.StorageManager;
|
||||
import com.cloud.storage.StoragePool;
|
||||
import com.cloud.storage.StoragePoolHostVO;
|
||||
|
|
@ -1052,6 +1054,11 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy
|
|||
Map<Volume, List<StoragePool>> suitableVolumeStoragePools = new HashMap<Volume, List<StoragePool>>();
|
||||
List<Volume> readyAndReusedVolumes = new ArrayList<Volume>();
|
||||
|
||||
// There should be atleast the ROOT volume of the VM in usable state
|
||||
if (volumesTobeCreated.isEmpty()) {
|
||||
throw new CloudRuntimeException("Unable to create deployment, no usable volumes found for the VM");
|
||||
}
|
||||
|
||||
// for each volume find list of suitable storage pools by calling the
|
||||
// allocators
|
||||
for (VolumeVO toBeCreated : volumesTobeCreated) {
|
||||
|
|
@ -1076,11 +1083,24 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy
|
|||
if (!pool.isInMaintenance()) {
|
||||
if (!avoid.shouldAvoid(pool)) {
|
||||
long exstPoolDcId = pool.getDataCenterId();
|
||||
|
||||
long exstPoolPodId = pool.getPodId() != null ? pool.getPodId() : -1;
|
||||
long exstPoolClusterId = pool.getClusterId() != null ? pool.getClusterId() : -1;
|
||||
boolean canReusePool = false;
|
||||
if (plan.getDataCenterId() == exstPoolDcId && plan.getPodId() == exstPoolPodId
|
||||
&& plan.getClusterId() == exstPoolClusterId) {
|
||||
canReusePool = true;
|
||||
} else if (plan.getDataCenterId() == exstPoolDcId) {
|
||||
DataStore dataStore = this.dataStoreMgr.getPrimaryDataStore(pool.getId());
|
||||
if (dataStore != null && dataStore.getScope() != null
|
||||
&& dataStore.getScope().getScopeType() == ScopeType.ZONE) {
|
||||
canReusePool = true;
|
||||
}
|
||||
} else {
|
||||
s_logger.debug("Pool of the volume does not fit the specified plan, need to reallocate a pool for this volume");
|
||||
canReusePool = false;
|
||||
}
|
||||
|
||||
if (canReusePool) {
|
||||
s_logger.debug("Planner need not allocate a pool for this volume since its READY");
|
||||
suitablePools.add(pool);
|
||||
suitableVolumeStoragePools.put(toBeCreated, suitablePools);
|
||||
|
|
@ -1088,8 +1108,6 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy
|
|||
readyAndReusedVolumes.add(toBeCreated);
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
s_logger.debug("Pool of the volume does not fit the specified plan, need to reallocate a pool for this volume");
|
||||
}
|
||||
} else {
|
||||
s_logger.debug("Pool of the volume is in avoid set, need to reallocate a pool for this volume");
|
||||
|
|
|
|||
|
|
@ -508,7 +508,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
|
|||
}
|
||||
addr.setState(assign ? IpAddress.State.Allocated : IpAddress.State.Allocating);
|
||||
|
||||
if (vlanUse != VlanType.DirectAttached || zone.getNetworkType() == NetworkType.Basic) {
|
||||
if (vlanUse != VlanType.DirectAttached) {
|
||||
addr.setAssociatedWithNetworkId(guestNetworkId);
|
||||
addr.setVpcId(vpcId);
|
||||
}
|
||||
|
|
@ -551,7 +551,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
|
|||
addr.getSystem(), addr.getClass().getName(), addr.getUuid());
|
||||
}
|
||||
// don't increment resource count for direct and dedicated ip addresses
|
||||
if (addr.getAssociatedWithNetworkId() != null && !isIpDedicated(addr)) {
|
||||
if (updateIpResourceCount(addr)) {
|
||||
_resourceLimitMgr.incrementResourceCount(owner.getId(), ResourceType.public_ip);
|
||||
}
|
||||
}
|
||||
|
|
@ -2519,6 +2519,10 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
|
|||
}
|
||||
|
||||
public boolean isDhcpAccrossMultipleSubnetsSupported(Network network) {
|
||||
if (!_networkModel.areServicesSupportedInNetwork(network.getId(), Service.Dhcp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DhcpServiceProvider dhcpServiceProvider = getDhcpServiceProvider(network);
|
||||
Map <Network.Capability, String> capabilities = dhcpServiceProvider.getCapabilities().get(Network.Service.Dhcp);
|
||||
String supportsMultipleSubnets = capabilities.get(Network.Capability.DhcpAccrossMultipleSubnets);
|
||||
|
|
@ -3779,7 +3783,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
|
|||
txn.start();
|
||||
|
||||
// don't decrement resource count for direct and dedicated ips
|
||||
if (ip.getAssociatedWithNetworkId() != null && !isIpDedicated(ip)) {
|
||||
if (updateIpResourceCount(ip)) {
|
||||
_resourceLimitMgr.decrementResourceCount(_ipAddressDao.findById(addrId).getAllocatedToAccountId(), ResourceType.public_ip);
|
||||
}
|
||||
|
||||
|
|
@ -3803,7 +3807,10 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
|
|||
|
||||
return ip;
|
||||
}
|
||||
|
||||
|
||||
protected boolean updateIpResourceCount(IPAddressVO ip) {
|
||||
return (ip.getAssociatedWithNetworkId() != null || ip.getVpcId() != null) && !isIpDedicated(ip);
|
||||
}
|
||||
|
||||
|
||||
Random _rand = new Random(System.currentTimeMillis());
|
||||
|
|
|
|||
|
|
@ -544,6 +544,8 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService,
|
|||
throws ResourceUnavailableException {
|
||||
boolean handled = false;
|
||||
switch (purpose){
|
||||
/* StaticNatRule would be applied by Firewall provider, since the incompatible of two object */
|
||||
case StaticNat:
|
||||
case Firewall:
|
||||
for (FirewallServiceProvider fwElement: _firewallElements) {
|
||||
Network.Provider provider = fwElement.getProvider();
|
||||
|
|
@ -568,18 +570,6 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService,
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case StaticNat:
|
||||
for (StaticNatServiceProvider element: _staticNatElements) {
|
||||
Network.Provider provider = element.getProvider();
|
||||
boolean isSnatProvider = _networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.StaticNat, provider);
|
||||
if (!isSnatProvider) {
|
||||
continue;
|
||||
}
|
||||
handled = element.applyStaticNats(network, (List<? extends StaticNat>) rules);
|
||||
if (handled)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
/* case NetworkACL:
|
||||
for (NetworkACLServiceProvider element: _networkAclElements) {
|
||||
Network.Provider provider = element.getProvider();
|
||||
|
|
|
|||
|
|
@ -3378,12 +3378,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
|
|||
|
||||
// password should be set only on default network element
|
||||
if (password != null && nic.isDefaultNic()) {
|
||||
String encodedPassword = PasswordGenerator.rot13(password);
|
||||
// We would unset password for BACKUP router in the RvR, to prevent user from accidently reset the
|
||||
// password again after BACKUP become MASTER
|
||||
if (router.getIsRedundantRouter() && router.getRedundantState() != RedundantState.MASTER) {
|
||||
encodedPassword = PasswordGenerator.rot13("saved_password");
|
||||
}
|
||||
final String encodedPassword = PasswordGenerator.rot13(password);
|
||||
SavePasswordCommand cmd = new SavePasswordCommand(encodedPassword, nic.getIp4Address(), profile.getVirtualMachine().getHostName(), _networkModel.getExecuteInSeqNtwkElmtCmd());
|
||||
cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, getRouterControlIp(router.getId()));
|
||||
cmd.setAccessDetail(NetworkElementCommand.ROUTER_GUEST_IP, getRouterIpInNetwork(nic.getNetworkId(), router.getId()));
|
||||
|
|
|
|||
|
|
@ -1920,9 +1920,23 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
|
|||
@Override
|
||||
public Host createHostAndAgent(Long hostId, ServerResource resource, Map<String, String> details, boolean old, List<String> hostTags,
|
||||
boolean forRebalance) {
|
||||
_agentMgr.tapLoadingAgents(hostId, TapAgentsAction.Add);
|
||||
Host host = createHostAndAgent(resource, details, old, hostTags, forRebalance);
|
||||
_agentMgr.tapLoadingAgents(hostId, TapAgentsAction.Del);
|
||||
Host host = null;
|
||||
if (_agentMgr.tapLoadingAgents(hostId, TapAgentsAction.Add)) {
|
||||
try {
|
||||
AgentAttache agentattache = _agentMgr.findAttache(hostId);
|
||||
if (agentattache == null) {
|
||||
s_logger.debug("Creating agent for host " + hostId);
|
||||
host = createHostAndAgent(resource, details, old, hostTags, forRebalance);
|
||||
s_logger.debug("Completed creating agent for host " + hostId);
|
||||
} else {
|
||||
s_logger.debug("Agent already created in another thread for host " + hostId + ", ignore this");
|
||||
}
|
||||
} finally {
|
||||
_agentMgr.tapLoadingAgents(hostId, TapAgentsAction.Del);
|
||||
}
|
||||
} else {
|
||||
s_logger.debug("Agent creation already getting processed in another thread for host " + hostId + ", ignore this");
|
||||
}
|
||||
return host;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -681,30 +681,39 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
|
|||
s_logger.debug("Trying to create " + volume + " on " + pool);
|
||||
}
|
||||
DataStore store = dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary);
|
||||
AsyncCallFuture<VolumeApiResult> future = null;
|
||||
boolean isNotCreatedFromTemplate = volume.getTemplateId() == null ? true : false;
|
||||
if (isNotCreatedFromTemplate) {
|
||||
future = volService.createVolumeAsync(volume, store);
|
||||
} else {
|
||||
TemplateInfo templ = tmplFactory.getTemplate(template.getId(), DataStoreRole.Image);
|
||||
future = volService.createVolumeFromTemplateAsync(volume, store.getId(), templ);
|
||||
}
|
||||
try {
|
||||
VolumeApiResult result = future.get();
|
||||
if (result.isFailed()) {
|
||||
s_logger.debug("create volume failed: " + result.getResult());
|
||||
throw new CloudRuntimeException("create volume failed:" + result.getResult());
|
||||
for (int i = 0; i < 2; i++) {
|
||||
// retry one more time in case of template reload is required for Vmware case
|
||||
AsyncCallFuture<VolumeApiResult> future = null;
|
||||
boolean isNotCreatedFromTemplate = volume.getTemplateId() == null ? true : false;
|
||||
if (isNotCreatedFromTemplate) {
|
||||
future = volService.createVolumeAsync(volume, store);
|
||||
} else {
|
||||
TemplateInfo templ = tmplFactory.getTemplate(template.getId(), DataStoreRole.Image);
|
||||
future = volService.createVolumeFromTemplateAsync(volume, store.getId(), templ);
|
||||
}
|
||||
try {
|
||||
VolumeApiResult result = future.get();
|
||||
if (result.isFailed()) {
|
||||
if (result.getResult().contains("request template reload") && (i == 0)) {
|
||||
s_logger.debug("Retry template re-deploy for vmware");
|
||||
continue;
|
||||
} else {
|
||||
s_logger.debug("create volume failed: " + result.getResult());
|
||||
throw new CloudRuntimeException("create volume failed:" + result.getResult());
|
||||
}
|
||||
}
|
||||
|
||||
return result.getVolume();
|
||||
} catch (InterruptedException e) {
|
||||
s_logger.error("create volume failed", e);
|
||||
throw new CloudRuntimeException("create volume failed", e);
|
||||
} catch (ExecutionException e) {
|
||||
s_logger.error("create volume failed", e);
|
||||
throw new CloudRuntimeException("create volume failed", e);
|
||||
return result.getVolume();
|
||||
} catch (InterruptedException e) {
|
||||
s_logger.error("create volume failed", e);
|
||||
throw new CloudRuntimeException("create volume failed", e);
|
||||
} catch (ExecutionException e) {
|
||||
s_logger.error("create volume failed", e);
|
||||
throw new CloudRuntimeException("create volume failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
throw new CloudRuntimeException("create volume failed even after template re-deploy");
|
||||
}
|
||||
|
||||
public String getRandomVolumeName() {
|
||||
|
|
@ -2528,31 +2537,41 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
|
|||
}
|
||||
VolumeInfo volume = volFactory.getVolume(newVol.getId(), destPool);
|
||||
Long templateId = newVol.getTemplateId();
|
||||
AsyncCallFuture<VolumeApiResult> future = null;
|
||||
if (templateId == null) {
|
||||
future = volService.createVolumeAsync(volume, destPool);
|
||||
} else {
|
||||
TemplateInfo templ = tmplFactory.getTemplate(templateId, DataStoreRole.Image);
|
||||
future = volService.createVolumeFromTemplateAsync(volume, destPool.getId(), templ);
|
||||
}
|
||||
VolumeApiResult result = null;
|
||||
try {
|
||||
result = future.get();
|
||||
if (result.isFailed()) {
|
||||
s_logger.debug("Unable to create "
|
||||
+ newVol + ":" + result.getResult());
|
||||
throw new StorageUnavailableException("Unable to create "
|
||||
+ newVol + ":" + result.getResult(), destPool.getId());
|
||||
for (int i = 0; i < 2; i++) {
|
||||
// retry one more time in case of template reload is required for Vmware case
|
||||
AsyncCallFuture<VolumeApiResult> future = null;
|
||||
if (templateId == null) {
|
||||
future = volService.createVolumeAsync(volume, destPool);
|
||||
} else {
|
||||
TemplateInfo templ = tmplFactory.getTemplate(templateId, DataStoreRole.Image);
|
||||
future = volService.createVolumeFromTemplateAsync(volume, destPool.getId(), templ);
|
||||
}
|
||||
VolumeApiResult result = null;
|
||||
try {
|
||||
result = future.get();
|
||||
if (result.isFailed()) {
|
||||
if (result.getResult().contains("request template reload") && (i == 0)) {
|
||||
s_logger.debug("Retry template re-deploy for vmware");
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
s_logger.debug("Unable to create "
|
||||
+ newVol + ":" + result.getResult());
|
||||
throw new StorageUnavailableException("Unable to create "
|
||||
+ newVol + ":" + result.getResult(), destPool.getId());
|
||||
}
|
||||
}
|
||||
newVol = _volsDao.findById(newVol.getId());
|
||||
break; //break out of template-redeploy retry loop
|
||||
} catch (InterruptedException e) {
|
||||
s_logger.error("Unable to create " + newVol, e);
|
||||
throw new StorageUnavailableException("Unable to create "
|
||||
+ newVol + ":" + e.toString(), destPool.getId());
|
||||
} catch (ExecutionException e) {
|
||||
s_logger.error("Unable to create " + newVol, e);
|
||||
throw new StorageUnavailableException("Unable to create "
|
||||
+ newVol + ":" + e.toString(), destPool.getId());
|
||||
}
|
||||
newVol = _volsDao.findById(newVol.getId());
|
||||
} catch (InterruptedException e) {
|
||||
s_logger.error("Unable to create " + newVol, e);
|
||||
throw new StorageUnavailableException("Unable to create "
|
||||
+ newVol + ":" + e.toString(), destPool.getId());
|
||||
} catch (ExecutionException e) {
|
||||
s_logger.error("Unable to create " + newVol, e);
|
||||
throw new StorageUnavailableException("Unable to create "
|
||||
+ newVol + ":" + e.toString(), destPool.getId());
|
||||
}
|
||||
|
||||
return new Pair<VolumeVO, DataStore>(newVol, destPool);
|
||||
|
|
@ -2638,7 +2657,8 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
|
|||
public boolean canVmRestartOnAnotherServer(long vmId) {
|
||||
List<VolumeVO> vols = _volsDao.findCreatedByInstance(vmId);
|
||||
for (VolumeVO vol : vols) {
|
||||
if (!vol.isRecreatable() && !vol.getPoolType().isShared()) {
|
||||
StoragePoolVO storagePoolVO = _storagePoolDao.findById(vol.getPoolId());
|
||||
if (!vol.isRecreatable() && storagePoolVO != null && storagePoolVO.getPoolType() != null && !(storagePoolVO.getPoolType().isShared())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -743,7 +743,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
|
|||
DataStore store = templateMgr.getImageStore(dataCenterId, template.getId());
|
||||
if (store == null) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("No secondary storage available in zone " + dataCenterId + ", wait until it is ready to launch secondary storage vm");
|
||||
s_logger.debug("Secondary storage VM template " + template.getId() + " is not available in zone " + dataCenterId + ", wait until it is ready to launch secondary storage vm");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1403,16 +1403,22 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
//getting the prent volume
|
||||
long parentVolumeId=_snapshotDao.findById(snapshotId).getVolumeId();
|
||||
VolumeVO parentVolume = _volumeDao.findById(parentVolumeId);
|
||||
if (parentVolume != null && parentVolume.getIsoId() != null) {
|
||||
if (parentVolume != null && parentVolume.getIsoId() != null && parentVolume.getIsoId() != 0) {
|
||||
privateTemplate.setSourceTemplateId(parentVolume.getIsoId());
|
||||
_tmpltDao.update(privateTemplate.getId(), privateTemplate);
|
||||
} else if (parentVolume != null && parentVolume.getTemplateId() != null) {
|
||||
privateTemplate.setSourceTemplateId(parentVolume.getTemplateId());
|
||||
_tmpltDao.update(privateTemplate.getId(), privateTemplate);
|
||||
}
|
||||
}
|
||||
else if (volumeId != null) {
|
||||
VolumeVO parentVolume = _volumeDao.findById(volumeId);
|
||||
if (parentVolume.getIsoId() != null) {
|
||||
if (parentVolume.getIsoId() != null && parentVolume.getIsoId() != 0) {
|
||||
privateTemplate.setSourceTemplateId(parentVolume.getIsoId());
|
||||
_tmpltDao.update(privateTemplate.getId(), privateTemplate);
|
||||
} else if (parentVolume.getTemplateId() != null) {
|
||||
privateTemplate.setSourceTemplateId(parentVolume.getTemplateId());
|
||||
_tmpltDao.update(privateTemplate.getId(), privateTemplate);
|
||||
}
|
||||
}
|
||||
TemplateDataStoreVO srcTmpltStore = this._tmplStoreDao.findByStoreTemplate(store.getId(), templateId);
|
||||
|
|
|
|||
|
|
@ -1479,8 +1479,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
|
|||
}
|
||||
|
||||
//Update Resource Count for the given account
|
||||
_resourceLimitMgr.incrementResourceCount(account.getId(),
|
||||
ResourceType.volume, new Long(volumes.size()));
|
||||
resourceCountIncrement(account.getId(), new Long(serviceOffering.getCpu()),
|
||||
new Long(serviceOffering.getRamSize()));
|
||||
txn.commit();
|
||||
|
|
@ -4879,6 +4877,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
|
|||
} else {
|
||||
newVol = volumeMgr.allocateDuplicateVolume(root, null);
|
||||
}
|
||||
// Save usage event and update resource count for user vm volumes
|
||||
if (vm instanceof UserVm) {
|
||||
_resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.volume);
|
||||
}
|
||||
|
||||
_volsDao.attachVolume(newVol.getId(), vmId, newVol.getDeviceId());
|
||||
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ import com.cloud.user.Account;
|
|||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.AccountService;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.ResourceLimitService;
|
||||
import com.cloud.user.UserContext;
|
||||
import com.cloud.user.UserVO;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
|
|
@ -104,6 +105,8 @@ public class UserVmManagerTest {
|
|||
@Mock List<VolumeVO> _rootVols;
|
||||
@Mock Account _accountMock2;
|
||||
@Mock ServiceOfferingDao _offeringDao;
|
||||
@Mock ResourceLimitService _resourceLimitMgr;
|
||||
|
||||
@Before
|
||||
public void setup(){
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
|
@ -121,6 +124,7 @@ public class UserVmManagerTest {
|
|||
_userVmMgr._configMgr = _configMgr;
|
||||
_userVmMgr._offeringDao= _offeringDao;
|
||||
_userVmMgr._capacityMgr = _capacityMgr;
|
||||
_userVmMgr._resourceLimitMgr = _resourceLimitMgr;
|
||||
_userVmMgr._scaleRetry = 2;
|
||||
|
||||
doReturn(3L).when(_account).getId();
|
||||
|
|
@ -488,4 +492,4 @@ public class UserVmManagerTest {
|
|||
_userVmMgr.moveVMToUser(cmd);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -526,6 +526,14 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
|
|||
SwiftUtil.putObject(swift, properties, containterName, _tmpltpp);
|
||||
}
|
||||
|
||||
//clean up template data on staging area
|
||||
try {
|
||||
DeleteCommand deleteCommand = new DeleteCommand(newTemplate);
|
||||
execute(deleteCommand);
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Failed to clean up staging area:", e);
|
||||
}
|
||||
|
||||
TemplateObjectTO template = new TemplateObjectTO();
|
||||
template.setPath(swiftPath);
|
||||
template.setSize(templateFile.length());
|
||||
|
|
@ -543,7 +551,15 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
|
|||
TemplateObjectTO newTemplate = (TemplateObjectTO)answer.getNewData();
|
||||
newTemplate.setDataStore(srcDataStore);
|
||||
CopyCommand newCpyCmd = new CopyCommand(newTemplate, destData, cmd.getWait(), cmd.executeInSequence());
|
||||
return copyFromNfsToS3(newCpyCmd);
|
||||
Answer result = copyFromNfsToS3(newCpyCmd);
|
||||
//clean up template data on staging area
|
||||
try {
|
||||
DeleteCommand deleteCommand = new DeleteCommand(newTemplate);
|
||||
execute(deleteCommand);
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Failed to clean up staging area:", e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
s_logger.debug("Failed to create templat from snapshot");
|
||||
|
|
@ -1775,7 +1791,15 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
|
|||
parent += File.separator;
|
||||
}
|
||||
String absoluteVolumePath = parent + relativeVolumePath;
|
||||
File tmpltParent = new File(absoluteVolumePath).getParentFile();
|
||||
File volPath = new File(absoluteVolumePath);
|
||||
File tmpltParent = null;
|
||||
if (volPath.exists() && volPath.isDirectory()) {
|
||||
// for vmware, absoluteVolumePath represents a directory where volume files are located.
|
||||
tmpltParent = volPath;
|
||||
} else{
|
||||
// for other hypervisors, the volume .vhd or .qcow2 file path is passed
|
||||
tmpltParent = new File(absoluteVolumePath).getParentFile();
|
||||
}
|
||||
String details = null;
|
||||
if (!tmpltParent.exists()) {
|
||||
details = "volume parent directory " + tmpltParent.getName() + " doesn't exist";
|
||||
|
|
@ -1806,7 +1830,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
|
|||
|
||||
if (!f.delete()) {
|
||||
return new Answer(cmd, false, "Unable to delete file " + f.getName() + " under Volume path "
|
||||
+ relativeVolumePath);
|
||||
+ tmpltParent.getPath());
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
|
|
@ -1816,7 +1840,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
|
|||
}
|
||||
if (!tmpltParent.delete()) {
|
||||
details = "Unable to delete directory " + tmpltParent.getName() + " under Volume path "
|
||||
+ relativeVolumePath;
|
||||
+ tmpltParent.getPath();
|
||||
s_logger.debug(details);
|
||||
return new Answer(cmd, false, details);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
# 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.
|
||||
|
|
@ -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
|
||||
|
|
@ -24,13 +24,13 @@ from marvin.integration.lib.base import (
|
|||
Account,
|
||||
ServiceOffering,
|
||||
VirtualMachine,
|
||||
Domain
|
||||
Domain,
|
||||
Resources
|
||||
)
|
||||
from marvin.integration.lib.common import (get_domain,
|
||||
get_zone,
|
||||
get_template,
|
||||
cleanup_resources,
|
||||
get_updated_resource_count,
|
||||
find_suitable_host,
|
||||
get_resource_type
|
||||
)
|
||||
|
|
@ -96,9 +96,9 @@ class TestCPULimits(cloudstackTestCase):
|
|||
cls.services = Services().services
|
||||
# Get Zone, Domain and templates
|
||||
cls.domain = get_domain(cls.api_client, cls.services)
|
||||
cls.zone = get_zone(cls.api_client, cls.services)
|
||||
cls.zone = get_zone(cls.api_client, cls.services)
|
||||
cls.services["mode"] = cls.zone.networktype
|
||||
|
||||
|
||||
cls.template = get_template(
|
||||
cls.api_client,
|
||||
cls.zone.id,
|
||||
|
|
@ -106,11 +106,11 @@ class TestCPULimits(cloudstackTestCase):
|
|||
)
|
||||
|
||||
cls.services["virtual_machine"]["zoneid"] = cls.zone.id
|
||||
|
||||
|
||||
cls.service_offering = ServiceOffering.create(
|
||||
cls.api_client,
|
||||
cls.services["service_offering"]
|
||||
)
|
||||
)
|
||||
|
||||
cls._cleanup = [cls.service_offering, ]
|
||||
return
|
||||
|
|
@ -149,44 +149,53 @@ class TestCPULimits(cloudstackTestCase):
|
|||
return
|
||||
|
||||
def createInstance(self, service_off, networks=None, api_client=None):
|
||||
"""Creates an instance in account"""
|
||||
|
||||
if api_client is None:
|
||||
api_client = self.apiclient
|
||||
"""Creates an instance in account
|
||||
"""
|
||||
if api_client is None:
|
||||
api_client = self.apiclient
|
||||
|
||||
self.debug("Deploying an instance in account: %s" %
|
||||
self.account.name)
|
||||
self.account.name)
|
||||
try:
|
||||
vm = VirtualMachine.create(
|
||||
api_client,
|
||||
self.services["virtual_machine"],
|
||||
templateid=self.template.id,
|
||||
accountid=self.account.name,
|
||||
domainid=self.account.domainid,
|
||||
networkids=networks,
|
||||
serviceofferingid=service_off.id)
|
||||
api_client,
|
||||
self.services["virtual_machine"],
|
||||
templateid=self.template.id,
|
||||
accountid=self.account.name,
|
||||
domainid=self.account.domainid,
|
||||
networkids=networks,
|
||||
serviceofferingid=service_off.id)
|
||||
vms = VirtualMachine.list(api_client, id=vm.id, listall=True)
|
||||
self.assertIsInstance(vms,
|
||||
list,
|
||||
"List VMs should return a valid response")
|
||||
list,
|
||||
"List VMs should return a valid response")
|
||||
self.assertEqual(vms[0].state, "Running",
|
||||
"Vm state should be running after deployment")
|
||||
"Vm state should be running after deployment")
|
||||
return vm
|
||||
except Exception as e:
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_01_multiplecore_reboot_instance(self):
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_01_multiplecore_start_stop_instance(self):
|
||||
"""Test Deploy VM with multiple core CPU & verify the usage"""
|
||||
|
||||
# Validate the following
|
||||
# 1. Deploy VM with multiple core CPU & verify the usage
|
||||
# 2. Stop VM & verify the update resource limit of Root Admin Account
|
||||
# 3. Start VM & verify the update resource limit of Root Admin Account
|
||||
# 4. Resource count should list properly.
|
||||
# 2. Stop VM & verify the update resource count of Root Admin Account
|
||||
# 3. Start VM & verify the update resource count of Root Admin Account
|
||||
# 4. Resource count should list properly.
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].cputotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["cpunumber"])
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Resource count should match with the expected resource count")
|
||||
|
||||
self.debug("Stopping instance: %s" % self.vm.name)
|
||||
try:
|
||||
|
|
@ -194,8 +203,15 @@ class TestCPULimits(cloudstackTestCase):
|
|||
except Exception as e:
|
||||
self.fail("Failed to stop instance: %s" % e)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_stop = account_list[0].cputotal
|
||||
|
||||
self.assertEqual(resource_count, resource_count_after_stop,
|
||||
"Resource count should be same after stopping the instance")
|
||||
|
||||
self.debug("Starting instance: %s" % self.vm.name)
|
||||
try:
|
||||
|
|
@ -203,21 +219,37 @@ class TestCPULimits(cloudstackTestCase):
|
|||
except Exception as e:
|
||||
self.fail("Failed to start instance: %s" % e)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_start = account_list[0].cputotal
|
||||
|
||||
self.assertEqual(resource_count, resource_count_after_start,
|
||||
"Resource count should be same after stopping the instance")
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_02_multiplecore_migrate_instance(self):
|
||||
"""Test Deploy VM with multiple core CPU & verify the usage"""
|
||||
|
||||
# Validate the following
|
||||
# 1. Deploy VM with multiple core CPU & verify the usage
|
||||
# 2. Migrate VM & verify update resource limit of Root Admin Account
|
||||
# 3. Resource count should list properly.
|
||||
# 1. Deploy VM with multiple core CPU & verify the usage
|
||||
# 2. Migrate VM & verify updated resource count of Root Admin Account
|
||||
# 3. Resource count should list properly.
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].cputotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["cpunumber"])
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Resource count should match with the expected resource count")
|
||||
|
||||
host = find_suitable_host(self.apiclient, self.vm)
|
||||
self.debug("Migrating instance: %s to host: %s" % (self.vm.name, host.name))
|
||||
|
|
@ -225,22 +257,38 @@ class TestCPULimits(cloudstackTestCase):
|
|||
self.vm.migrate(self.apiclient, host.id)
|
||||
except Exception as e:
|
||||
self.fail("Failed to migrate instance: %s" % e)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_migrate = account_list[0].cputotal
|
||||
|
||||
self.assertEqual(resource_count, resource_count_after_migrate,
|
||||
"Resource count should be same after migrating the instance")
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_03_multiplecore_delete_instance(self):
|
||||
"""Test Deploy VM with multiple core CPU & verify the usage"""
|
||||
|
||||
# Validate the following
|
||||
# 1. Deploy VM with multiple core CPU & verify the usage
|
||||
# 2. Destroy VM & verify update resource limit of Root Admin Account
|
||||
# 1. Deploy VM with multiple core CPU & verify the usage
|
||||
# 2. Destroy VM & verify update resource count of Root Admin Account
|
||||
# 3. Resource count should list properly.
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].cputotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["cpunumber"])
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Resource count should match with the expected resource count")
|
||||
|
||||
self.debug("Destroying instance: %s" % self.vm.name)
|
||||
try:
|
||||
|
|
@ -248,23 +296,27 @@ class TestCPULimits(cloudstackTestCase):
|
|||
except Exception as e:
|
||||
self.fail("Failed to delete instance: %s" % e)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].cputotal
|
||||
self.assertEqual(resource_count, 0 , "Resource count for %s should be 0" % get_resource_type(resource_id=8))#CPU
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_04_deploy_multiple_vm_with_multiple_cpus(self):
|
||||
"""Test Deploy multiple VM with 4 core CPU & verify the usage"""
|
||||
|
||||
# Validate the following
|
||||
# 1. Create compute offering with 4 core CPU
|
||||
# 2. Deploy multiple VMs with this service offering
|
||||
# 3. Update Resource count for the root admin CPU usage
|
||||
# 3. List Resource count for the root admin CPU usage
|
||||
# 4. CPU usage should list properly
|
||||
# 5. Destroy one VM among multiple VM's and verify the resource limit
|
||||
# 5. Destroy one VM among multiple VM's and verify the resource count
|
||||
# 6. Migrate VM from & verify resource updates
|
||||
# 7. List resources of Root Admin for CPU
|
||||
# 7. List resource count for Root Admin
|
||||
# 8. Failed to deploy VM and verify the resource usage
|
||||
|
||||
self.debug("Creating service offering with 4 CPU cores")
|
||||
|
|
@ -279,31 +331,18 @@ class TestCPULimits(cloudstackTestCase):
|
|||
self.service_offering.name)
|
||||
vm_1 = self.createInstance(service_off=self.service_offering)
|
||||
vm_2 = self.createInstance(service_off=self.service_offering)
|
||||
self.createInstance(service_off=self.service_offering)
|
||||
self.createInstance(service_off=self.service_offering)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
|
||||
self.debug("Destroying instance: %s" % vm_1.name)
|
||||
try:
|
||||
vm_1.delete(self.apiclient)
|
||||
except Exception as e:
|
||||
self.fail("Failed to delete instance: %s" % e)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
|
||||
host = find_suitable_host(self.apiclient, vm_2)
|
||||
self.debug("Migrating instance: %s to host: %s" % (vm_2.name,
|
||||
host.name))
|
||||
try:
|
||||
vm_2.migrate(self.apiclient, host.id)
|
||||
except Exception as e:
|
||||
self.fail("Failed to migrate instance: %s" % e)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].cputotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["cpunumber"]) * 4 #Total 4 Vms
|
||||
self.assertTrue(resource_count == expected_resource_count,
|
||||
"Resource count does not match the expected vavlue")
|
||||
return
|
||||
|
||||
class TestDomainCPULimitsConfiguration(cloudstackTestCase):
|
||||
|
|
@ -357,214 +396,262 @@ class TestDomainCPULimitsConfiguration(cloudstackTestCase):
|
|||
return
|
||||
|
||||
def createInstance(self, service_off, networks=None, api_client=None):
|
||||
"""Creates an instance in account"""
|
||||
|
||||
if api_client is None:
|
||||
api_client = self.apiclient
|
||||
"""Creates an instance in account
|
||||
"""
|
||||
if api_client is None:
|
||||
api_client = self.apiclient
|
||||
|
||||
self.debug("Deploying an instance in account: %s" %
|
||||
self.account.name)
|
||||
self.account.name)
|
||||
try:
|
||||
vm = VirtualMachine.create(
|
||||
api_client,
|
||||
self.services["virtual_machine"],
|
||||
templateid=self.template.id,
|
||||
accountid=self.account.name,
|
||||
domainid=self.account.domainid,
|
||||
networkids=networks,
|
||||
serviceofferingid=service_off.id)
|
||||
api_client,
|
||||
self.services["virtual_machine"],
|
||||
templateid=self.template.id,
|
||||
accountid=self.account.name,
|
||||
domainid=self.account.domainid,
|
||||
networkids=networks,
|
||||
serviceofferingid=service_off.id)
|
||||
vms = VirtualMachine.list(api_client, id=vm.id, listall=True)
|
||||
self.assertIsInstance(vms,
|
||||
list,
|
||||
"List VMs should return a valid response")
|
||||
list,
|
||||
"List VMs should return a valid response")
|
||||
self.assertEqual(vms[0].state, "Running",
|
||||
"Vm state should be running after deployment")
|
||||
"Vm state should be running after deployment")
|
||||
return vm
|
||||
except Exception as e:
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
|
||||
def setupAccounts(self):
|
||||
|
||||
self.debug("Creating a sub-domain under: %s" % self.domain.name)
|
||||
self.child_domain = Domain.create(
|
||||
self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.domain.id
|
||||
)
|
||||
self.child_do_admin = Account.create(
|
||||
self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True,
|
||||
domainid=self.child_domain.id
|
||||
)
|
||||
# Cleanup the resources created at end of test
|
||||
self.cleanup.append(self.child_do_admin)
|
||||
self.cleanup.append(self.child_domain)
|
||||
self.child_domain_1 = Domain.create(
|
||||
self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.domain.id
|
||||
)
|
||||
self.child_do_admin_1 = Account.create(
|
||||
self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True,
|
||||
domainid=self.child_domain_1.id
|
||||
)
|
||||
# Cleanup the resources created at end of test
|
||||
self.cleanup.append(self.child_do_admin_1)
|
||||
self.cleanup.append(self.child_domain_1)
|
||||
|
||||
self.domain = Domain.create(
|
||||
self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.domain.id
|
||||
)
|
||||
self.child_domain_2 = Domain.create(
|
||||
self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.domain.id
|
||||
)
|
||||
|
||||
self.admin = Account.create(
|
||||
self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True,
|
||||
domainid=self.domain.id
|
||||
)
|
||||
self.child_do_admin_2 = Account.create(
|
||||
self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True,
|
||||
domainid=self.child_domain_2.id
|
||||
)
|
||||
|
||||
# Cleanup the resources created at end of test
|
||||
self.cleanup.append(self.child_do_admin_2)
|
||||
self.cleanup.append(self.child_domain_2)
|
||||
|
||||
# Cleanup the resources created at end of test
|
||||
self.cleanup.append(self.admin)
|
||||
self.cleanup.append(self.domain)
|
||||
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(configuration='max.account.cpus')
|
||||
def test_01_reboot_instance(self):
|
||||
def test_01_stop_start_instance(self):
|
||||
"""Test Deploy VM with 4 core CPU & verify the usage"""
|
||||
#keep the configuration value - max.account.cpus number = 10
|
||||
|
||||
# Validate the following
|
||||
# 1. Create compute offering with 4 core CPU & Deploy VM
|
||||
# 2. Update Resource count CPU usage
|
||||
# 3. Reboot instance, check resource count.
|
||||
# 2. List Resource count CPU usage
|
||||
# 3. Stop and Start instance, check resource count.
|
||||
# 4. Resource count should list properly.
|
||||
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts()
|
||||
users = {self.domain: self.admin,
|
||||
self.child_domain: self.child_do_admin
|
||||
users = {self.child_domain_1: self.child_do_admin_1,
|
||||
self.child_domain_2: self.child_do_admin_2
|
||||
}
|
||||
for domain, admin in users.items():
|
||||
self.account = admin
|
||||
self.domain = domain
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
|
||||
self.debug("Creating an instance with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
vm = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
self.debug("Creating an instance with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
vm = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].cputotal
|
||||
|
||||
self.debug("Stopping instance: %s" % vm.name)
|
||||
try:
|
||||
vm.stop(self.apiclient)
|
||||
except Exception as e:
|
||||
self.fail("Failed to stop instance: %s" % e)
|
||||
expected_resource_count = int(self.services["service_offering"]["cpunumber"])
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Initial resource count should match with the expected resource count")
|
||||
|
||||
self.debug("Starting instance: %s" % vm.name)
|
||||
try:
|
||||
vm.start(self.apiclient)
|
||||
except Exception as e:
|
||||
self.fail("Failed to start instance: %s" % e)
|
||||
self.debug("Stopping instance: %s" % vm.name)
|
||||
try:
|
||||
vm.stop(self.apiclient)
|
||||
except Exception as e:
|
||||
self.fail("Failed to stop instance: %s" % e)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_stop = account_list[0].cputotal
|
||||
|
||||
self.assertEqual(resource_count, resource_count_after_stop,
|
||||
"Resource count should be same after stopping the instance")
|
||||
|
||||
self.debug("Starting instance: %s" % vm.name)
|
||||
try:
|
||||
vm.start(self.apiclient)
|
||||
except Exception as e:
|
||||
self.fail("Failed to start instance: %s" % e)
|
||||
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_start = account_list[0].cputotal
|
||||
|
||||
self.assertEqual(resource_count_after_stop, resource_count_after_start,
|
||||
"Resource count should be same after starting the instance")
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(configuration='max.account.cpus')
|
||||
def test_02_migrate_instance(self):
|
||||
"""Test Deploy VM with 4 core CPU & verify the usage"""
|
||||
#keep the configuration value - max.account.cpus number = 10
|
||||
|
||||
# Validate the following
|
||||
# 1. Create compute offering with 4 core CPU & Deploy VM
|
||||
# 2. Update Resource count
|
||||
# 2. List Resource count
|
||||
# 3. Migrate instance to another host
|
||||
# 4. Resource count should list properly.
|
||||
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts()
|
||||
users = {self.domain: self.admin,
|
||||
self.child_domain: self.child_do_admin
|
||||
users = {self.child_domain_1: self.child_do_admin_1,
|
||||
self.child_domain_2: self.child_do_admin_2
|
||||
}
|
||||
for domain, admin in users.items():
|
||||
self.account = admin
|
||||
self.domain = domain
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
|
||||
self.debug("Creating an instance with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
vm = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
self.debug("Creating an instance with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
vm = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].cputotal
|
||||
|
||||
host = find_suitable_host(self.apiclient, vm)
|
||||
self.debug("Migrating instance: %s to host: %s" %
|
||||
(vm.name, host.name))
|
||||
try:
|
||||
vm.migrate(self.apiclient, host.id)
|
||||
except Exception as e:
|
||||
self.fail("Failed to migrate instance: %s" % e)
|
||||
expected_resource_count = int(self.services["service_offering"]["cpunumber"])
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Initial resource count should with the expected resource count")
|
||||
|
||||
host = find_suitable_host(self.apiclient, vm)
|
||||
self.debug("Migrating instance: %s to host: %s" %
|
||||
(vm.name, host.name))
|
||||
try:
|
||||
vm.migrate(self.apiclient, host.id)
|
||||
except Exception as e:
|
||||
self.fail("Failed to migrate instance: %s" % e)
|
||||
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_migrate = account_list[0].cputotal
|
||||
|
||||
self.assertEqual(resource_count, resource_count_after_migrate,
|
||||
"Resource count should be same after starting the instance")
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(configuration='max.account.cpus')
|
||||
def test_03_delete_instance(self):
|
||||
"""Test Deploy VM with 4 core CPU & verify the usage"""
|
||||
#keep the configuration value - max.account.cpus number = 10
|
||||
|
||||
# Validate the following
|
||||
# 1. Create compute offering with 4 core CPU & Deploy VM
|
||||
# 2. Update Resource count for te CPU usage
|
||||
# 2. List Resource count for the CPU usage
|
||||
# 3. Delete instance
|
||||
# 4. Resource count should list as 0
|
||||
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts()
|
||||
users = {self.domain: self.admin,
|
||||
self.child_domain: self.child_do_admin
|
||||
users = {self.child_domain_1: self.child_do_admin_1,
|
||||
self.child_domain_2: self.child_do_admin_2
|
||||
}
|
||||
for domain, admin in users.items():
|
||||
self.account = admin
|
||||
self.domain = domain
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
|
||||
self.debug("Creating an instance with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
vm = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
self.debug("Creating an instance with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
vm = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].cputotal
|
||||
|
||||
self.debug("Destroying instance: %s" % vm.name)
|
||||
try:
|
||||
vm.delete(self.apiclient)
|
||||
except Exception as e:
|
||||
self.fail("Failed to delete instance: %s" % e)
|
||||
expected_resource_count = int(self.services["service_offering"]["cpunumber"])
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
self.assertEqual(resource_count, 0 , "Resource count for %s should be 0" % get_resource_type(resource_id=8))#CPU
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Initial resource count should match with the expected resource count")
|
||||
|
||||
self.debug("Destroying instance: %s" % vm.name)
|
||||
try:
|
||||
vm.delete(self.apiclient)
|
||||
except Exception as e:
|
||||
self.fail("Failed to delete instance: %s" % e)
|
||||
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].cputotal
|
||||
self.assertEqual(resource_count, 0, "Resource count for %s should be 0" % get_resource_type(resource_id=8))#CPU
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(configuration='max.account.cpus')
|
||||
@attr(configuration='max.account.cpus')
|
||||
def test_04_deploy_multiple_vm_with_multiple_cpus(self):
|
||||
"""Test Deploy multiple VM with 4 core CPU & verify the usage"""
|
||||
#keep the configuration value - max.account.cpus number = 16
|
||||
|
||||
#keep the configuration value - max.account.cpus number = 16
|
||||
# Validate the following
|
||||
# 1. Create compute offering with 4 core CPU
|
||||
# 2. Deploy multiple VMs with this service offering
|
||||
# 3. Update Resource count for the root admin CPU usage
|
||||
# 3. List Resource count for the root admin CPU usage
|
||||
# 4. CPU usage should list properly
|
||||
|
||||
self.debug("Creating service offering with 4 CPU cores")
|
||||
|
|
@ -577,19 +664,28 @@ class TestDomainCPULimitsConfiguration(cloudstackTestCase):
|
|||
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts()
|
||||
users = {self.domain: self.admin,
|
||||
self.child_domain: self.child_do_admin
|
||||
users = {self.child_domain_1: self.child_do_admin_1,
|
||||
self.child_domain_2: self.child_do_admin_2
|
||||
}
|
||||
for domain, admin in users.items():
|
||||
self.account = admin
|
||||
self.domain = domain
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
cpu_account_gc = Resources.list(self.apiclient,
|
||||
resourcetype = 8, #CPU
|
||||
account = self.account.name,
|
||||
domainid = self.domain.id
|
||||
)
|
||||
|
||||
if cpu_account_gc[0].max != 16:
|
||||
self.skipTest("This test case requires configuration value max.account.cpus to be 16")
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
|
||||
self.debug("Creating an instance with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
self.service_offering.name)
|
||||
vm_1 = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
vm_2 = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
|
|
@ -599,8 +695,17 @@ class TestDomainCPULimitsConfiguration(cloudstackTestCase):
|
|||
with self.assertRaises(Exception):
|
||||
self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].cputotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["cpunumber"]) * 4 #Total 4 vms
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Initial resource count should with the expected resource count")
|
||||
|
||||
self.debug("Destroying instance: %s" % vm_1.name)
|
||||
try:
|
||||
|
|
@ -608,8 +713,17 @@ class TestDomainCPULimitsConfiguration(cloudstackTestCase):
|
|||
except Exception as e:
|
||||
self.fail("Failed to delete instance: %s" % e)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_delete = account_list[0].cputotal
|
||||
|
||||
expected_resource_count -= int(self.services["service_offering"]["cpunumber"])
|
||||
|
||||
self.assertEqual(resource_count_after_delete, expected_resource_count,
|
||||
"Resource count should be less than before after deleting the instance")
|
||||
|
||||
host = find_suitable_host(self.apiclient, vm_2)
|
||||
self.debug("Migrating instance: %s to host: %s" % (vm_2.name,
|
||||
|
|
@ -619,6 +733,13 @@ class TestDomainCPULimitsConfiguration(cloudstackTestCase):
|
|||
except Exception as e:
|
||||
self.fail("Failed to migrate instance: %s" % e)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
return
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_migrate = account_list[0].cputotal
|
||||
|
||||
self.debug(resource_count_after_migrate)
|
||||
self.assertEqual(resource_count_after_delete, resource_count_after_migrate,
|
||||
"Resource count should be same after migrating the instance")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -31,7 +31,6 @@ from marvin.integration.lib.common import (get_domain,
|
|||
get_zone,
|
||||
get_template,
|
||||
cleanup_resources,
|
||||
get_updated_resource_count,
|
||||
find_suitable_host,
|
||||
get_resource_type
|
||||
)
|
||||
|
|
@ -140,89 +139,90 @@ class TestDomainCPULimitsUpdateResources(cloudstackTestCase):
|
|||
def createInstance(self, service_off, networks=None, api_client=None):
|
||||
"""Creates an instance in account"""
|
||||
|
||||
if api_client is None:
|
||||
api_client = self.apiclient
|
||||
if api_client is None:
|
||||
api_client = self.apiclient
|
||||
|
||||
self.debug("Deploying an instance in account: %s" %
|
||||
self.account.name)
|
||||
self.account.name)
|
||||
try:
|
||||
vm = VirtualMachine.create(
|
||||
api_client,
|
||||
self.services["virtual_machine"],
|
||||
templateid=self.template.id,
|
||||
accountid=self.account.name,
|
||||
domainid=self.account.domainid,
|
||||
networkids=networks,
|
||||
serviceofferingid=service_off.id)
|
||||
api_client,
|
||||
self.services["virtual_machine"],
|
||||
templateid=self.template.id,
|
||||
accountid=self.account.name,
|
||||
domainid=self.account.domainid,
|
||||
networkids=networks,
|
||||
serviceofferingid=service_off.id)
|
||||
vms = VirtualMachine.list(api_client, id=vm.id, listall=True)
|
||||
self.assertIsInstance(vms,
|
||||
list,
|
||||
"List VMs should return a valid response")
|
||||
list,
|
||||
"List VMs should return a valid response")
|
||||
self.assertEqual(vms[0].state, "Running",
|
||||
"Vm state should be running after deployment")
|
||||
"Vm state should be running after deployment")
|
||||
return vm
|
||||
except Exception as e:
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
|
||||
def setupAccounts(self):
|
||||
|
||||
self.debug("Creating a sub-domain under: %s" % self.domain.name)
|
||||
self.child_domain = Domain.create(
|
||||
self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.domain.id
|
||||
)
|
||||
self.child_do_admin = Account.create(
|
||||
self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True,
|
||||
domainid=self.child_domain.id
|
||||
)
|
||||
# Cleanup the resources created at end of test
|
||||
self.cleanup.append(self.child_do_admin)
|
||||
self.cleanup.append(self.child_domain)
|
||||
|
||||
Resources.updateLimit(
|
||||
self.apiclient,
|
||||
resourcetype=8,
|
||||
max=16,
|
||||
account=self.child_do_admin.name,
|
||||
domainid=self.child_do_admin.domainid
|
||||
)
|
||||
self.child_domain = Domain.create(
|
||||
self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.domain.id
|
||||
)
|
||||
self.child_do_admin = Account.create(
|
||||
self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True,
|
||||
domainid=self.child_domain.id
|
||||
)
|
||||
# Cleanup the resources created at end of test
|
||||
self.cleanup.append(self.child_do_admin)
|
||||
self.cleanup.append(self.child_domain)
|
||||
|
||||
self.domain = Domain.create(
|
||||
self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.domain.id
|
||||
)
|
||||
Resources.updateLimit(
|
||||
self.apiclient,
|
||||
resourcetype=8,
|
||||
max=16,
|
||||
account=self.child_do_admin.name,
|
||||
domainid=self.child_do_admin.domainid
|
||||
)
|
||||
|
||||
self.admin = Account.create(
|
||||
self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True,
|
||||
domainid=self.domain.id
|
||||
)
|
||||
self.domain = Domain.create(
|
||||
self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.domain.id
|
||||
)
|
||||
|
||||
# Cleanup the resources created at end of test
|
||||
self.cleanup.append(self.admin)
|
||||
self.cleanup.append(self.domain)
|
||||
self.admin = Account.create(
|
||||
self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True,
|
||||
domainid=self.domain.id
|
||||
)
|
||||
|
||||
Resources.updateLimit(
|
||||
self.apiclient,
|
||||
resourcetype=8,
|
||||
max=16,
|
||||
account=self.admin.name,
|
||||
domainid=self.admin.domainid
|
||||
)
|
||||
# Cleanup the resources created at end of test
|
||||
self.cleanup.append(self.admin)
|
||||
self.cleanup.append(self.domain)
|
||||
|
||||
Resources.updateLimit(
|
||||
self.apiclient,
|
||||
resourcetype=8,
|
||||
max=16,
|
||||
account=self.admin.name,
|
||||
domainid=self.admin.domainid
|
||||
)
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_01_multiple_core_vm_reboot_instance(self):
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_01_multiple_core_vm_start_stop_instance(self):
|
||||
"""Test Deploy VM with 4 core CPU & verify the usage"""
|
||||
|
||||
# Validate the following
|
||||
# 1. Create two domains and set specific resource (cpu) limit for them
|
||||
# 2. Create compute offering with 4 core CPU & deploy vm
|
||||
# 2. Create compute offering with 4 core CPU & deploy vm
|
||||
# 3. Update Resource count for the domains
|
||||
# 4. Reboot instance and check resource count
|
||||
# 5. Resource count should list properly.
|
||||
|
|
@ -236,16 +236,25 @@ class TestDomainCPULimitsUpdateResources(cloudstackTestCase):
|
|||
self.account = admin
|
||||
self.domain = domain
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
|
||||
self.debug("Creating an instance with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
self.service_offering.name)
|
||||
vm = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].cputotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["cpunumber"])
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Initial resource count should match with the expected resource count")
|
||||
|
||||
self.debug("Stopping instance: %s" % vm.name)
|
||||
try:
|
||||
|
|
@ -253,8 +262,15 @@ class TestDomainCPULimitsUpdateResources(cloudstackTestCase):
|
|||
except Exception as e:
|
||||
self.fail("Failed to stop instance: %s" % e)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_stop = account_list[0].cputotal
|
||||
|
||||
self.assertEqual(resource_count, resource_count_after_stop,
|
||||
"Resource count should be same as before, after stopping the instance")
|
||||
|
||||
self.debug("Starting instance: %s" % vm.name)
|
||||
try:
|
||||
|
|
@ -262,20 +278,27 @@ class TestDomainCPULimitsUpdateResources(cloudstackTestCase):
|
|||
except Exception as e:
|
||||
self.fail("Failed to start instance: %s" % e)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_start = account_list[0].cputotal
|
||||
|
||||
self.assertEqual(resource_count_after_stop, resource_count_after_start,
|
||||
"Resource count should be same as before, after starting the instance")
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_02_multiple_core_vm_migrate_instance(self):
|
||||
"""Test Deploy VM with 4 core CPU & verify the usage"""
|
||||
|
||||
# Validate the following
|
||||
# 1. Create two domains and set specific resource (cpu) limit for them
|
||||
# 2. Create compute offering with 4 core CPU & deploy vm
|
||||
# 2. Create compute offering with 4 core CPU & deploy vm
|
||||
# 3. Update Resource count for the domains
|
||||
# 4. Migrate instance to new host and check resource count
|
||||
# 5. Resource count should list properly.
|
||||
# 5. Resource count should list properly.
|
||||
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts()
|
||||
|
|
@ -286,39 +309,55 @@ class TestDomainCPULimitsUpdateResources(cloudstackTestCase):
|
|||
self.account = admin
|
||||
self.domain = domain
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
|
||||
self.debug("Creating an instance with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
self.service_offering.name)
|
||||
vm = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].cputotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["cpunumber"])
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Initial resource count should match with the expected resource count")
|
||||
|
||||
host = find_suitable_host(self.apiclient, vm)
|
||||
self.debug("Migrating instance: %s to host: %s" %
|
||||
(vm.name, host.name))
|
||||
(vm.name, host.name))
|
||||
try:
|
||||
vm.migrate(self.apiclient, host.id)
|
||||
except Exception as e:
|
||||
self.fail("Failed to migrate instance: %s" % e)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_migrate = account_list[0].cputotal
|
||||
|
||||
self.assertEqual(resource_count, resource_count_after_migrate,
|
||||
"Resource count should be same as before, after migrating the instance")
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_03_multiple_core_vm_delete_instance(self):
|
||||
"""Test Deploy VM with 4 core CPU & verify the usage"""
|
||||
|
||||
# Validate the following
|
||||
# 1. Create two domains and set specific resource (cpu) limit for them
|
||||
# 2. Create compute offering with 4 core CPU & deploy vm
|
||||
# 2. Create compute offering with 4 core CPU & deploy vm
|
||||
# 3. Update Resource count for the domains
|
||||
# 4. delete instance and check resource count
|
||||
# 5. Resource count should list properly.
|
||||
# 5. Resource count should list properly.
|
||||
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts()
|
||||
|
|
@ -329,16 +368,25 @@ class TestDomainCPULimitsUpdateResources(cloudstackTestCase):
|
|||
self.account = admin
|
||||
self.domain = domain
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
|
||||
self.debug("Creating an instance with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
self.service_offering.name)
|
||||
vm = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].cputotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["cpunumber"])
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Initial resource count should with the expected resource count")
|
||||
|
||||
self.debug("Destroying instance: %s" % vm.name)
|
||||
try:
|
||||
|
|
@ -346,12 +394,18 @@ class TestDomainCPULimitsUpdateResources(cloudstackTestCase):
|
|||
except Exception as e:
|
||||
self.fail("Failed to delete instance: %s" % e)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
self.assertEqual(resource_count, 0 , "Resource count for %s should be 0" % get_resource_type(resource_id=8))#CPU
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_delete = account_list[0].cputotal
|
||||
|
||||
self.assertEqual(resource_count_after_delete, 0,
|
||||
"Resource count for %s should be 0" % get_resource_type(resource_id=8))#CPU
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_04_deploy_multiple_vm_with_multiple_core(self):
|
||||
"""Test Deploy multiple VM with 4 core CPU & verify the usage"""
|
||||
|
||||
|
|
@ -378,12 +432,12 @@ class TestDomainCPULimitsUpdateResources(cloudstackTestCase):
|
|||
self.account = admin
|
||||
self.domain = domain
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
|
||||
self.debug("Creating an instance with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
self.service_offering.name)
|
||||
vm_1 = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
vm_2 = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
|
|
@ -393,8 +447,17 @@ class TestDomainCPULimitsUpdateResources(cloudstackTestCase):
|
|||
with self.assertRaises(Exception):
|
||||
self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].cputotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["cpunumber"]) * 4 #Total 4 VMs
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Initial resource count should be 4")
|
||||
|
||||
self.debug("Destroying instance: %s" % vm_1.name)
|
||||
try:
|
||||
|
|
@ -402,8 +465,17 @@ class TestDomainCPULimitsUpdateResources(cloudstackTestCase):
|
|||
except Exception as e:
|
||||
self.fail("Failed to delete instance: %s" % e)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_delete = account_list[0].cputotal
|
||||
|
||||
expected_resource_count -= int(self.services["service_offering"]["cpunumber"])
|
||||
|
||||
self.assertEqual(resource_count_after_delete, expected_resource_count,
|
||||
"Resource count should match with the expected count")
|
||||
|
||||
host = find_suitable_host(self.apiclient, vm_2)
|
||||
self.debug("Migrating instance: %s to host: %s" % (vm_2.name,
|
||||
|
|
@ -413,8 +485,15 @@ class TestDomainCPULimitsUpdateResources(cloudstackTestCase):
|
|||
except Exception as e:
|
||||
self.fail("Failed to migrate instance: %s" % e)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_migrate = account_list[0].cputotal
|
||||
|
||||
self.assertEqual(resource_count_after_migrate, resource_count_after_delete,
|
||||
"Resource count should not change after migrating the instance")
|
||||
return
|
||||
|
||||
class TestMultipleChildDomains(cloudstackTestCase):
|
||||
|
|
@ -465,120 +544,120 @@ class TestMultipleChildDomains(cloudstackTestCase):
|
|||
def createInstance(self, account, service_off, networks=None, api_client=None):
|
||||
"""Creates an instance in account"""
|
||||
|
||||
if api_client is None:
|
||||
api_client = self.apiclient
|
||||
if api_client is None:
|
||||
api_client = self.apiclient
|
||||
|
||||
self.debug("Deploying an instance in account: %s" %
|
||||
account.name)
|
||||
account.name)
|
||||
try:
|
||||
vm = VirtualMachine.create(
|
||||
api_client,
|
||||
self.services["virtual_machine"],
|
||||
templateid=self.template.id,
|
||||
accountid=account.name,
|
||||
domainid=account.domainid,
|
||||
networkids=networks,
|
||||
serviceofferingid=service_off.id)
|
||||
api_client,
|
||||
self.services["virtual_machine"],
|
||||
templateid=self.template.id,
|
||||
accountid=account.name,
|
||||
domainid=account.domainid,
|
||||
networkids=networks,
|
||||
serviceofferingid=service_off.id)
|
||||
vms = VirtualMachine.list(api_client, id=vm.id, listall=True)
|
||||
self.assertIsInstance(vms,
|
||||
list,
|
||||
"List VMs should return a valid response")
|
||||
list,
|
||||
"List VMs should return a valid response")
|
||||
self.assertEqual(vms[0].state, "Running",
|
||||
"Vm state should be running after deployment")
|
||||
"Vm state should be running after deployment")
|
||||
return vm
|
||||
except Exception as e:
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
|
||||
def setupAccounts(self):
|
||||
|
||||
self.debug("Creating a domain under: %s" % self.domain.name)
|
||||
self.parent_domain = Domain.create(self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.domain.id)
|
||||
self.parentd_admin = Account.create(
|
||||
self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True,
|
||||
domainid=self.domain.id
|
||||
)
|
||||
|
||||
self.debug("Updating the Memory resource limit for domain: %s" %
|
||||
self.domain.name)
|
||||
Resources.updateLimit(self.apiclient,
|
||||
resourcetype=8,
|
||||
max=10,
|
||||
domainid=self.parentd_admin.domainid,
|
||||
account=self.parentd_admin.name)
|
||||
self.debug("Creating a sub-domain under: %s" % self.parent_domain.name)
|
||||
self.cdomain_1 = Domain.create(self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.parent_domain.id)
|
||||
self.parent_domain = Domain.create(self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.domain.id)
|
||||
self.parentd_admin = Account.create(
|
||||
self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True,
|
||||
domainid=self.domain.id
|
||||
)
|
||||
|
||||
self.debug("Creating a sub-domain under: %s" % self.parent_domain.name)
|
||||
self.cdomain_2 = Domain.create(self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.parent_domain.id)
|
||||
self.debug("Updating the Memory resource limit for domain: %s" %
|
||||
self.domain.name)
|
||||
Resources.updateLimit(self.apiclient,
|
||||
resourcetype=8,
|
||||
max=10,
|
||||
domainid=self.parentd_admin.domainid,
|
||||
account=self.parentd_admin.name)
|
||||
self.debug("Creating a sub-domain under: %s" % self.parent_domain.name)
|
||||
self.cdomain_1 = Domain.create(self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.parent_domain.id)
|
||||
|
||||
self.cadmin_1 = Account.create(
|
||||
self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True,
|
||||
domainid=self.cdomain_1.id
|
||||
)
|
||||
self.debug("Creating a sub-domain under: %s" % self.parent_domain.name)
|
||||
self.cdomain_2 = Domain.create(self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.parent_domain.id)
|
||||
|
||||
self.debug("Updating the Memory resource count for domain: %s" %
|
||||
self.cdomain_1.name)
|
||||
Resources.updateLimit(self.apiclient,
|
||||
resourcetype=8,
|
||||
max=4,
|
||||
domainid=self.cadmin_1.domainid)
|
||||
|
||||
self.debug("Updating the Memory resource count for account: %s" %
|
||||
self.cadmin_1.name)
|
||||
Resources.updateLimit(self.apiclient,
|
||||
resourcetype=8,
|
||||
max=2,
|
||||
account=self.cadmin_1.name,
|
||||
domainid=self.cadmin_1.domainid)
|
||||
|
||||
self.cadmin_2 = Account.create(
|
||||
self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True,
|
||||
domainid=self.cdomain_2.id
|
||||
)
|
||||
self.cadmin_1 = Account.create(
|
||||
self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True,
|
||||
domainid=self.cdomain_1.id
|
||||
)
|
||||
|
||||
self.debug("Updating the Memory resource count for domain: %s" %
|
||||
self.cdomain_2.name)
|
||||
Resources.updateLimit(self.apiclient,
|
||||
resourcetype=8,
|
||||
max=4,
|
||||
domainid=self.cadmin_2.domainid)
|
||||
self.cdomain_1.name)
|
||||
Resources.updateLimit(self.apiclient,
|
||||
resourcetype=8,
|
||||
max=4,
|
||||
domainid=self.cadmin_1.domainid)
|
||||
|
||||
self.debug("Updating the Memory resource count for account: %s" %
|
||||
self.cadmin_2.name)
|
||||
Resources.updateLimit(self.apiclient,
|
||||
resourcetype=8,
|
||||
max=2,
|
||||
account=self.cadmin_2.name,
|
||||
domainid=self.cadmin_2.domainid)
|
||||
self.cadmin_1.name)
|
||||
Resources.updateLimit(self.apiclient,
|
||||
resourcetype=8,
|
||||
max=2,
|
||||
account=self.cadmin_1.name,
|
||||
domainid=self.cadmin_1.domainid)
|
||||
|
||||
# Cleanup the resources created at end of test
|
||||
self.cleanup.append(self.cadmin_1)
|
||||
self.cleanup.append(self.cadmin_2)
|
||||
self.cleanup.append(self.cdomain_1)
|
||||
self.cleanup.append(self.cdomain_2)
|
||||
self.cleanup.append(self.parentd_admin)
|
||||
self.cleanup.append(self.parent_domain)
|
||||
|
||||
users = {
|
||||
self.parent_domain: self.parentd_admin,
|
||||
self.cdomain_1: self.cadmin_1,
|
||||
self.cdomain_2: self.cadmin_2
|
||||
}
|
||||
self.cadmin_2 = Account.create(
|
||||
self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True,
|
||||
domainid=self.cdomain_2.id
|
||||
)
|
||||
|
||||
self.debug("Updating the Memory resource count for domain: %s" %
|
||||
self.cdomain_2.name)
|
||||
Resources.updateLimit(self.apiclient,
|
||||
resourcetype=8,
|
||||
max=5,
|
||||
domainid=self.cadmin_2.domainid)
|
||||
|
||||
self.debug("Updating the Memory resource count for account: %s" %
|
||||
self.cadmin_2.name)
|
||||
Resources.updateLimit(self.apiclient,
|
||||
resourcetype=8,
|
||||
max=3,
|
||||
account=self.cadmin_2.name,
|
||||
domainid=self.cadmin_2.domainid)
|
||||
# Cleanup the resources created at end of test
|
||||
self.cleanup.append(self.cadmin_1)
|
||||
self.cleanup.append(self.cadmin_2)
|
||||
self.cleanup.append(self.cdomain_1)
|
||||
self.cleanup.append(self.cdomain_2)
|
||||
self.cleanup.append(self.parentd_admin)
|
||||
self.cleanup.append(self.parent_domain)
|
||||
|
||||
users = {
|
||||
self.parent_domain: self.parentd_admin,
|
||||
self.cdomain_1: self.cadmin_1,
|
||||
self.cdomain_2: self.cadmin_2
|
||||
}
|
||||
return users
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_01_multiple_child_domains(self):
|
||||
"""Test CPU limits with multiple child domains"""
|
||||
|
||||
|
|
@ -589,7 +668,7 @@ class TestMultipleChildDomains(cloudstackTestCase):
|
|||
# 2. Deploy VM's by Domain1 admin1/user1/ Domain2 user1/Admin1 account
|
||||
# and verify the resource updates
|
||||
# 3. Deploy VM by admin account after reaching max parent domain limit
|
||||
# 4. Deploy VM with child account after reaching max child domain limit
|
||||
# 4. Deploy VM with child account after reaching max child domain limit
|
||||
# 5. Destroy user/admin account VM's and verify the child & Parent
|
||||
# domain resource updates
|
||||
|
||||
|
|
@ -605,41 +684,54 @@ class TestMultipleChildDomains(cloudstackTestCase):
|
|||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts()
|
||||
|
||||
api_client_cadmin_1 = self.testClient.createUserApiClient(
|
||||
UserName=self.cadmin_1.name,
|
||||
DomainName=self.cadmin_1.domain)
|
||||
api_client_cadmin_1 = self.testClient.createUserApiClient(
|
||||
UserName=self.cadmin_1.name,
|
||||
DomainName=self.cadmin_1.domain)
|
||||
|
||||
api_client_cadmin_2 = self.testClient.createUserApiClient(
|
||||
UserName=self.cadmin_2.name,
|
||||
DomainName=self.cadmin_2.domain)
|
||||
api_client_cadmin_2 = self.testClient.createUserApiClient(
|
||||
UserName=self.cadmin_2.name,
|
||||
DomainName=self.cadmin_2.domain)
|
||||
|
||||
self.debug("Creating an instance with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
self.service_offering.name)
|
||||
vm_1 = self.createInstance(account=self.cadmin_1,
|
||||
service_off=self.service_offering, api_client=api_client_cadmin_1)
|
||||
service_off=self.service_offering, api_client=api_client_cadmin_1)
|
||||
|
||||
vm_2 = self.createInstance(account=self.cadmin_2,
|
||||
service_off=self.service_offering, api_client=api_client_cadmin_2)
|
||||
service_off=self.service_offering, api_client=api_client_cadmin_2)
|
||||
|
||||
self.debug("Checking resource count for account: %s" % self.cadmin_1.name)
|
||||
resource_count_cadmin_1 = get_updated_resource_count(self.apiclient, account=self.cadmin_1, rtype=8)#CPU
|
||||
|
||||
account_list = Account.list(self.apiclient, id=self.cadmin_1.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_cadmin_1 = account_list[0].cputotal
|
||||
|
||||
self.debug(resource_count_cadmin_1)
|
||||
|
||||
self.debug("Checking resource count for account: %s" % self.cadmin_2.name)
|
||||
resource_count_cadmin_2 = get_updated_resource_count(self.apiclient, account=self.cadmin_2, rtype=8)#CPU
|
||||
account_list = Account.list(self.apiclient, id=self.cadmin_2.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_cadmin_2 = account_list[0].cputotal
|
||||
|
||||
self.debug(resource_count_cadmin_2)
|
||||
|
||||
self.debug(
|
||||
"Creating instance when CPU limit is fully used in parent domain")
|
||||
"Creating instance when CPU limit is fully used in child domain 1")
|
||||
with self.assertRaises(Exception):
|
||||
self.createInstance(account=self.cadmin_1,
|
||||
service_off=self.service_offering, api_client=api_client_cadmin_1)
|
||||
service_off=self.service_offering, api_client=api_client_cadmin_1)
|
||||
|
||||
self.debug(
|
||||
"Creating instance when CPU limit is fully used in child domain")
|
||||
"Creating instance when CPU limit is fully used in child domain 2")
|
||||
with self.assertRaises(Exception):
|
||||
self.createInstance(account=self.cadmin_1,
|
||||
service_off=self.service_offering, api_client=api_client_cadmin_1)
|
||||
self.createInstance(account=self.cadmin_2,
|
||||
service_off=self.service_offering, api_client=api_client_cadmin_2)
|
||||
self.debug("Destroying instances: %s, %s" % (vm_1.name, vm_2.name))
|
||||
try:
|
||||
vm_1.delete(self.apiclient)
|
||||
|
|
@ -648,12 +740,25 @@ class TestMultipleChildDomains(cloudstackTestCase):
|
|||
self.fail("Failed to delete instance: %s" % e)
|
||||
|
||||
self.debug("Checking resource count for account: %s" % self.cadmin_1.name)
|
||||
resource_count_cadmin_1 = get_updated_resource_count(self.apiclient, account=self.cadmin_1, rtype=8)#CPU
|
||||
|
||||
account_list = Account.list(self.apiclient, id=self.cadmin_1.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_cadmin_1 = account_list[0].cputotal
|
||||
|
||||
self.debug(resource_count_cadmin_1)
|
||||
self.assertEqual(resource_count_cadmin_1, 0 , "Resource count for %s should be 0" % get_resource_type(resource_id=8))#CPU
|
||||
self.assertEqual(resource_count_cadmin_1, 0, "Resource count for %s should be 0" % get_resource_type(resource_id=8))#CPU
|
||||
|
||||
self.debug("Checking resource count for account: %s" % self.cadmin_2.name)
|
||||
resource_count_cadmin_2 = get_updated_resource_count(self.apiclient, account=self.cadmin_2, rtype=8)#CPU
|
||||
account_list = Account.list(self.apiclient, id=self.cadmin_2.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_cadmin_2 = account_list[0].cputotal
|
||||
|
||||
self.debug(resource_count_cadmin_2)
|
||||
self.assertEqual(resource_count_cadmin_2, 0 , "Resource count for %s should be 0" % get_resource_type(resource_id=8))#CPU
|
||||
self.assertEqual(resource_count_cadmin_2, 0, "Resource count for %s should be 0" % get_resource_type(resource_id=8))#CPU
|
||||
return
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -31,8 +31,7 @@ from marvin.integration.lib.base import (
|
|||
from marvin.integration.lib.common import (get_domain,
|
||||
get_zone,
|
||||
get_template,
|
||||
cleanup_resources,
|
||||
get_updated_resource_count
|
||||
cleanup_resources
|
||||
)
|
||||
|
||||
class Services:
|
||||
|
|
@ -135,28 +134,28 @@ class TestMaxCPULimits(cloudstackTestCase):
|
|||
project=None, networks=None, api_client=None):
|
||||
"""Creates an instance in account"""
|
||||
|
||||
if api_client is None:
|
||||
api_client = self.apiclient
|
||||
if api_client is None:
|
||||
api_client = self.apiclient
|
||||
|
||||
self.debug("Deploying instance")
|
||||
try:
|
||||
if account:
|
||||
vm = VirtualMachine.create(
|
||||
api_client,
|
||||
self.services["virtual_machine"],
|
||||
templateid=self.template.id,
|
||||
accountid=account.name,
|
||||
domainid=account.domainid,
|
||||
networkids=networks,
|
||||
serviceofferingid=service_off.id)
|
||||
api_client,
|
||||
self.services["virtual_machine"],
|
||||
templateid=self.template.id,
|
||||
accountid=account.name,
|
||||
domainid=account.domainid,
|
||||
networkids=networks,
|
||||
serviceofferingid=service_off.id)
|
||||
elif project:
|
||||
vm = VirtualMachine.create(
|
||||
api_client,
|
||||
self.services["virtual_machine"],
|
||||
templateid=self.template.id,
|
||||
projectid=project.id,
|
||||
networkids=networks,
|
||||
serviceofferingid=service_off.id)
|
||||
api_client,
|
||||
self.services["virtual_machine"],
|
||||
templateid=self.template.id,
|
||||
projectid=project.id,
|
||||
networkids=networks,
|
||||
serviceofferingid=service_off.id)
|
||||
vms = VirtualMachine.list(api_client, id=vm.id, listall=True)
|
||||
self.assertIsInstance(vms,
|
||||
list,
|
||||
|
|
@ -165,67 +164,66 @@ class TestMaxCPULimits(cloudstackTestCase):
|
|||
"Vm state should be running after deployment")
|
||||
return vm
|
||||
except Exception as e:
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
|
||||
def setupAccounts(self, account_limit=2, domain_limit=2, project_limit=2):
|
||||
|
||||
self.debug("Creating a domain under: %s" % self.domain.name)
|
||||
self.child_domain = Domain.create(self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.domain.id)
|
||||
self.debug("Creating a domain under: %s" % self.domain.name)
|
||||
self.child_domain = Domain.create(self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.domain.id)
|
||||
|
||||
self.debug("domain crated with domain id %s" % self.child_domain.id)
|
||||
|
||||
self.debug("domain crated with domain id %s" % self.child_domain.id)
|
||||
self.child_do_admin = Account.create(self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True,
|
||||
domainid=self.child_domain.id)
|
||||
|
||||
self.child_do_admin = Account.create(self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True,
|
||||
domainid=self.child_domain.id)
|
||||
self.debug("domain admin created for domain id %s" %
|
||||
self.child_do_admin.domainid)
|
||||
|
||||
self.debug("domain admin created for domain id %s" %
|
||||
self.child_do_admin.domainid)
|
||||
# Create project as a domain admin
|
||||
self.project = Project.create(self.apiclient,
|
||||
self.services["project"],
|
||||
account=self.child_do_admin.name,
|
||||
domainid=self.child_do_admin.domainid)
|
||||
# Cleanup created project at end of test
|
||||
self.cleanup.append(self.project)
|
||||
|
||||
# Create project as a domain admin
|
||||
self.project = Project.create(self.apiclient,
|
||||
self.services["project"],
|
||||
account=self.child_do_admin.name,
|
||||
domainid=self.child_do_admin.domainid)
|
||||
# Cleanup created project at end of test
|
||||
self.cleanup.append(self.project)
|
||||
# Cleanup accounts created
|
||||
self.cleanup.append(self.child_do_admin)
|
||||
self.cleanup.append(self.child_domain)
|
||||
|
||||
# Cleanup accounts created
|
||||
self.cleanup.append(self.child_do_admin)
|
||||
self.cleanup.append(self.child_domain)
|
||||
self.debug("Updating the CPU resource count for domain: %s" %
|
||||
self.child_domain.name)
|
||||
# Update resource limits for account 1
|
||||
responses = Resources.updateLimit(self.apiclient,
|
||||
resourcetype=8,
|
||||
max=account_limit,
|
||||
account=self.child_do_admin.name,
|
||||
domainid=self.child_do_admin.domainid)
|
||||
|
||||
self.debug("Updating the CPU resource count for domain: %s" %
|
||||
self.child_domain.name)
|
||||
# Update resource limits for account 1
|
||||
responses = Resources.updateLimit(self.apiclient,
|
||||
resourcetype=8,
|
||||
max=account_limit,
|
||||
account=self.child_do_admin.name,
|
||||
domainid=self.child_do_admin.domainid)
|
||||
self.debug("CPU Resource count for child domain admin account is now: %s" %
|
||||
responses.max)
|
||||
|
||||
self.debug("CPU Resource count for child domain admin account is now: %s" %
|
||||
responses.max)
|
||||
self.debug("Updating the CPU limit for project")
|
||||
responses = Resources.updateLimit(self.apiclient,
|
||||
resourcetype=8,
|
||||
max=project_limit,
|
||||
projectid=self.project.id)
|
||||
|
||||
self.debug("Updating the CPU limit for project")
|
||||
responses = Resources.updateLimit(self.apiclient,
|
||||
resourcetype=8,
|
||||
max=project_limit,
|
||||
projectid=self.project.id)
|
||||
self.debug("CPU Resource count for project is now")
|
||||
self.debug(responses.max)
|
||||
|
||||
self.debug("CPU Resource count for project is now")
|
||||
self.debug(responses.max)
|
||||
self.debug("Updating the CPU limit for domain only")
|
||||
responses = Resources.updateLimit(self.apiclient,
|
||||
resourcetype=8,
|
||||
max=domain_limit,
|
||||
domainid=self.child_domain.id)
|
||||
|
||||
self.debug("Updating the CPU limit for domain only")
|
||||
responses = Resources.updateLimit(self.apiclient,
|
||||
resourcetype=8,
|
||||
max=domain_limit,
|
||||
domainid=self.child_domain.id)
|
||||
|
||||
self.debug("CPU Resource count for domain %s with id %s is now %s" %
|
||||
(responses.domain, responses.domainid, responses.max))
|
||||
self.debug("CPU Resource count for domain %s with id %s is now %s" %
|
||||
(responses.domain, responses.domainid, responses.max))
|
||||
|
||||
return
|
||||
|
||||
|
|
@ -241,24 +239,25 @@ class TestMaxCPULimits(cloudstackTestCase):
|
|||
# with "resource limit exceeds"
|
||||
|
||||
self.debug("Creating service offering with 3 CPU cores")
|
||||
self.services["service_offering"]["cpunumber"] = 3
|
||||
|
||||
self.services["service_offering"]["cpunumber"] = 3
|
||||
self.service_offering = ServiceOffering.create(
|
||||
self.apiclient,
|
||||
self.services["service_offering"]
|
||||
)
|
||||
self.apiclient,
|
||||
self.services["service_offering"]
|
||||
)
|
||||
# Adding to cleanup list after execution
|
||||
self.cleanup.append(self.service_offering)
|
||||
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts(account_limit=4, domain_limit=2)
|
||||
|
||||
api_client_admin = self.testClient.createUserApiClient(
|
||||
UserName=self.child_do_admin.name,
|
||||
DomainName=self.child_do_admin.domain)
|
||||
api_client_admin = self.testClient.createUserApiClient(
|
||||
UserName=self.child_do_admin.name,
|
||||
DomainName=self.child_do_admin.domain)
|
||||
|
||||
with self.assertRaises(Exception):
|
||||
self.createInstance(account=self.child_do_admin,
|
||||
service_off=self.service_offering, api_client=api_client_admin)
|
||||
service_off=self.service_offering, api_client=api_client_admin)
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
|
|
@ -273,35 +272,33 @@ class TestMaxCPULimits(cloudstackTestCase):
|
|||
# with "resource limit exceeds"
|
||||
|
||||
self.debug("Creating service offering with 4 CPU cores")
|
||||
self.services["service_offering"]["cpunumber"] = 4
|
||||
|
||||
self.services["service_offering"]["cpunumber"] = 4
|
||||
self.service_offering = ServiceOffering.create(
|
||||
self.apiclient,
|
||||
self.services["service_offering"]
|
||||
)
|
||||
self.apiclient,
|
||||
self.services["service_offering"]
|
||||
)
|
||||
# Adding to cleanup list after execution
|
||||
self.cleanup.append(self.service_offering)
|
||||
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts(account_limit=6, domain_limit=8)
|
||||
|
||||
api_client_admin = self.testClient.createUserApiClient(
|
||||
UserName=self.child_do_admin.name,
|
||||
DomainName=self.child_do_admin.domain)
|
||||
|
||||
self.debug("Deploying instance with account: %s" %
|
||||
self.child_do_admin.name)
|
||||
api_client_admin = self.testClient.createUserApiClient(
|
||||
UserName=self.child_do_admin.name,
|
||||
DomainName=self.child_do_admin.domain)
|
||||
|
||||
self.debug("Deploying instance with account: %s" %
|
||||
self.child_do_admin.name)
|
||||
|
||||
self.createInstance(account=self.child_do_admin,
|
||||
service_off=self.service_offering, api_client=api_client_admin)
|
||||
service_off=self.service_offering, api_client=api_client_admin)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.child_do_admin, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
|
||||
self.debug("Deploying instance when CPU limit is reached in account")
|
||||
self.debug("Deploying instance when CPU limit is reached in account")
|
||||
|
||||
with self.assertRaises(Exception):
|
||||
self.createInstance(account=self.chid_do_admin,
|
||||
service_off=self.service_offering, api_client=api_client_admin)
|
||||
service_off=self.service_offering, api_client=api_client_admin)
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
|
|
@ -316,26 +313,27 @@ class TestMaxCPULimits(cloudstackTestCase):
|
|||
# with "resource limit exceeds"
|
||||
|
||||
self.debug("Creating service offering with 3 CPU cores")
|
||||
self.services["service_offering"]["cpunumber"] = 3
|
||||
|
||||
self.services["service_offering"]["cpunumber"] = 3
|
||||
self.service_offering = ServiceOffering.create(
|
||||
self.apiclient,
|
||||
self.services["service_offering"]
|
||||
)
|
||||
self.apiclient,
|
||||
self.services["service_offering"]
|
||||
)
|
||||
# Adding to cleanup list after execution
|
||||
self.cleanup.append(self.service_offering)
|
||||
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts(account_limit=4, domain_limit=4, project_limit=2)
|
||||
|
||||
api_client_admin = self.testClient.createUserApiClient(
|
||||
UserName=self.child_do_admin.name,
|
||||
DomainName=self.child_do_admin.domain)
|
||||
api_client_admin = self.testClient.createUserApiClient(
|
||||
UserName=self.child_do_admin.name,
|
||||
DomainName=self.child_do_admin.domain)
|
||||
|
||||
self.debug("Deploying instance in account 2 when CPU limit is reached")
|
||||
|
||||
with self.assertRaises(Exception):
|
||||
self.createInstance(project=self.project,
|
||||
service_off=self.service_offering, api_client=api_client_admin)
|
||||
service_off=self.service_offering, api_client=api_client_admin)
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
|
|
@ -350,32 +348,30 @@ class TestMaxCPULimits(cloudstackTestCase):
|
|||
# with "resource limit exceeds"
|
||||
|
||||
self.debug("Creating service offering with 4 CPU cores")
|
||||
self.services["service_offering"]["cpunumber"] = 4
|
||||
|
||||
self.services["service_offering"]["cpunumber"] = 4
|
||||
self.service_offering = ServiceOffering.create(
|
||||
self.apiclient,
|
||||
self.services["service_offering"]
|
||||
)
|
||||
self.apiclient,
|
||||
self.services["service_offering"]
|
||||
)
|
||||
# Adding to cleanup list after execution
|
||||
self.cleanup.append(self.service_offering)
|
||||
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts(account_limit=6, domain_limit=6, project_limit=6)
|
||||
|
||||
api_client_admin = self.testClient.createUserApiClient(
|
||||
UserName=self.child_do_admin.name,
|
||||
DomainName=self.child_do_admin.domain)
|
||||
api_client_admin = self.testClient.createUserApiClient(
|
||||
UserName=self.child_do_admin.name,
|
||||
DomainName=self.child_do_admin.domain)
|
||||
|
||||
self.debug("Deploying instance with account: %s" %
|
||||
self.child_do_admin.name)
|
||||
self.child_do_admin.name)
|
||||
self.createInstance(account=self.child_do_admin,
|
||||
service_off=self.service_offering, api_client=api_client_admin)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.child_do_admin, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
service_off=self.service_offering, api_client=api_client_admin)
|
||||
|
||||
self.debug("Deploying instance in project when CPU limit is reached in account")
|
||||
|
||||
with self.assertRaises(Exception):
|
||||
self.createInstance(project=self.project,
|
||||
service_off=self.service_offering)
|
||||
service_off=self.service_offering)
|
||||
return
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -31,7 +31,6 @@ from marvin.integration.lib.common import (get_domain,
|
|||
get_zone,
|
||||
get_template,
|
||||
cleanup_resources,
|
||||
get_updated_resource_count,
|
||||
find_suitable_host,
|
||||
get_resource_type
|
||||
)
|
||||
|
|
@ -109,7 +108,7 @@ class TestProjectsCPULimits(cloudstackTestCase):
|
|||
cls.service_offering = ServiceOffering.create(
|
||||
cls.api_client,
|
||||
cls.services["service_offering"]
|
||||
)
|
||||
)
|
||||
|
||||
cls._cleanup = [cls.service_offering, ]
|
||||
return
|
||||
|
|
@ -137,15 +136,15 @@ class TestProjectsCPULimits(cloudstackTestCase):
|
|||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupProjectAccounts()
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.admin.name,
|
||||
DomainName=self.admin.domain)
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.admin.name,
|
||||
DomainName=self.admin.domain)
|
||||
|
||||
self.debug("Creating an instance with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
self.service_offering.name)
|
||||
self.vm = self.createInstance(project=self.project,
|
||||
service_off=self.service_offering, api_client=api_client)
|
||||
|
||||
service_off=self.service_offering, api_client=api_client)
|
||||
|
||||
return
|
||||
|
||||
def tearDown(self):
|
||||
|
|
@ -160,26 +159,26 @@ class TestProjectsCPULimits(cloudstackTestCase):
|
|||
def createInstance(self, project, service_off, networks=None, api_client=None):
|
||||
"""Creates an instance in account"""
|
||||
|
||||
if api_client is None:
|
||||
api_client = self.api_client
|
||||
|
||||
if api_client is None:
|
||||
api_client = self.api_client
|
||||
|
||||
try:
|
||||
self.vm = VirtualMachine.create(
|
||||
api_client,
|
||||
self.services["virtual_machine"],
|
||||
templateid=self.template.id,
|
||||
projectid=project.id,
|
||||
networkids=networks,
|
||||
serviceofferingid=service_off.id)
|
||||
api_client,
|
||||
self.services["virtual_machine"],
|
||||
templateid=self.template.id,
|
||||
projectid=project.id,
|
||||
networkids=networks,
|
||||
serviceofferingid=service_off.id)
|
||||
vms = VirtualMachine.list(api_client, id=self.vm.id, listall=True)
|
||||
self.assertIsInstance(vms,
|
||||
list,
|
||||
"List VMs should return a valid response")
|
||||
list,
|
||||
"List VMs should return a valid response")
|
||||
self.assertEqual(vms[0].state, "Running",
|
||||
"Vm state should be running after deployment")
|
||||
"Vm state should be running after deployment")
|
||||
return self.vm
|
||||
except Exception as e:
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
|
||||
def setupProjectAccounts(self):
|
||||
|
||||
|
|
@ -217,20 +216,26 @@ class TestProjectsCPULimits(cloudstackTestCase):
|
|||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(configuration='max.projects.cpus')
|
||||
def test_01_project_counts_reboot_instance(self):
|
||||
"""Test max.projects.cpus global configuration"""
|
||||
def test_01_project_counts_start_stop_instance(self):
|
||||
|
||||
# Validate the following
|
||||
# 1. Set (max.project.cpus=10) as the max limit to
|
||||
# Domain1 (max.account.cpus=10)
|
||||
# 2. Assign account to projects and verify the resource updates
|
||||
# 3. Deploy VM with the accounts added to the project
|
||||
# 4. Stop VM of an accounts added to the project.
|
||||
# 5. Resource count should list properly.
|
||||
# 1. Assign account to projects and verify the resource updates
|
||||
# 2. Deploy VM with the accounts added to the project
|
||||
# 3. Stop VM of an accounts added to the project.
|
||||
# 4. Resource count should list properly.
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.admin, project=self.project, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
project_list = Project.list(self.apiclient, id=self.project.id, listall=True)
|
||||
self.debug(project_list)
|
||||
self.assertIsInstance(project_list,
|
||||
list,
|
||||
"List Projects should return a valid response"
|
||||
)
|
||||
resource_count = project_list[0].cputotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["cpunumber"])
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Resource count should match with the expected resource count")
|
||||
|
||||
self.debug("Stopping instance: %s" % self.vm.name)
|
||||
try:
|
||||
|
|
@ -238,8 +243,15 @@ class TestProjectsCPULimits(cloudstackTestCase):
|
|||
except Exception as e:
|
||||
self.fail("Failed to stop instance: %s" % e)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.admin, project=self.project, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
project_list = Project.list(self.apiclient, id=self.project.id, listall=True)
|
||||
self.assertIsInstance(project_list,
|
||||
list,
|
||||
"List Projects should return a valid response"
|
||||
)
|
||||
resource_count_after_stop = project_list[0].cputotal
|
||||
|
||||
self.assertEqual(resource_count, resource_count_after_stop,
|
||||
"Resource count should be same after stopping the instance")
|
||||
|
||||
self.debug("Starting instance: %s" % self.vm.name)
|
||||
try:
|
||||
|
|
@ -247,25 +259,37 @@ class TestProjectsCPULimits(cloudstackTestCase):
|
|||
except Exception as e:
|
||||
self.fail("Failed to start instance: %s" % e)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.admin, project=self.project, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
project_list = Project.list(self.apiclient, id=self.project.id, listall=True)
|
||||
self.assertIsInstance(project_list,
|
||||
list,
|
||||
"List Projects should return a valid response"
|
||||
)
|
||||
resource_count_after_start = project_list[0].cputotal
|
||||
|
||||
self.assertEqual(resource_count, resource_count_after_start,
|
||||
"Resource count should be same after starting the instance")
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(configuration='max.projects.cpus')
|
||||
def test_02_project_counts_migrate_instance(self):
|
||||
"""Test max.projects.cpus global configuration"""
|
||||
|
||||
# Validate the following
|
||||
# 1. Set (max.project.cpus=10) as the max limit to
|
||||
# Domain1 (max.account.cpus=10)
|
||||
# 2. Assign account to projects and verify the resource updates
|
||||
# 3. Deploy VM with the accounts added to the project
|
||||
# 4. Migrate VM of an accounts added to the project to a new host
|
||||
# 5. Resource count should list properly.
|
||||
# 1. Assign account to projects and verify the resource updates
|
||||
# 2. Deploy VM with the accounts added to the project
|
||||
# 3. Migrate VM of an accounts added to the project to a new host
|
||||
# 4. Resource count should list properly.
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.admin, project=self.project, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
project_list = Project.list(self.apiclient, id=self.project.id, listall=True)
|
||||
self.assertIsInstance(project_list,
|
||||
list,
|
||||
"List Projects should return a valid response"
|
||||
)
|
||||
resource_count = project_list[0].cputotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["cpunumber"])
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Resource count should match with the expected resource count")
|
||||
|
||||
host = find_suitable_host(self.apiclient, self.vm)
|
||||
self.debug("Migrating instance: %s to host: %s" %
|
||||
|
|
@ -275,25 +299,37 @@ class TestProjectsCPULimits(cloudstackTestCase):
|
|||
except Exception as e:
|
||||
self.fail("Failed to migrate instance: %s" % e)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.admin, project=self.project, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
project_list = Project.list(self.apiclient, id=self.project.id, listall=True)
|
||||
self.assertIsInstance(project_list,
|
||||
list,
|
||||
"List Projects should return a valid response"
|
||||
)
|
||||
resource_count_after_migrate = project_list[0].cputotal
|
||||
|
||||
self.assertEqual(resource_count, resource_count_after_migrate,
|
||||
"Resource count should be same after migrating the instance")
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(configuration='max.projects.cpus')
|
||||
def test_03_project_counts_delete_instance(self):
|
||||
"""Test max.projects.cpus global configuration"""
|
||||
|
||||
# Validate the following
|
||||
# 1. Set (max.project.cpus=10) as the max limit to
|
||||
# Domain1 (max.account.cpus=10)
|
||||
# 2. Assign account to projects and verify the resource updates
|
||||
# 3. Deploy VM with the accounts added to the project
|
||||
# 4. Destroy VM of an accounts added to the project to a new host
|
||||
# 5. Resource count should list properly.
|
||||
# 1. Assign account to projects and verify the resource updates
|
||||
# 2. Deploy VM with the accounts added to the project
|
||||
# 3. Destroy VM of an accounts added to the project to a new host
|
||||
# 4. Resource count should list properly.
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.admin, project=self.project, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
project_list = Project.list(self.apiclient, id=self.project.id, listall=True)
|
||||
self.assertIsInstance(project_list,
|
||||
list,
|
||||
"List Projects should return a valid response"
|
||||
)
|
||||
resource_count = project_list[0].cputotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["cpunumber"])
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Resource count should match with the expected resource count")
|
||||
|
||||
self.debug("Destroying instance: %s" % self.vm.name)
|
||||
try:
|
||||
|
|
@ -301,7 +337,11 @@ class TestProjectsCPULimits(cloudstackTestCase):
|
|||
except Exception as e:
|
||||
self.fail("Failed to delete instance: %s" % e)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.admin, project=self.project, rtype=8)#CPU
|
||||
self.debug(resource_count)
|
||||
self.assertEqual(resource_count, 0 , "Resource count for %s should be 0" % get_resource_type(resource_id=8))#CPU
|
||||
project_list = Project.list(self.apiclient, id=self.project.id, listall=True)
|
||||
self.assertIsInstance(project_list,
|
||||
list,
|
||||
"List Projects should return a valid response"
|
||||
)
|
||||
resource_count_after_delete = project_list[0].cputotal
|
||||
self.assertEqual(resource_count_after_delete, 0 , "Resource count for %s should be 0" % get_resource_type(resource_id=8))#CPU
|
||||
return
|
||||
|
|
|
|||
|
|
@ -0,0 +1,290 @@
|
|||
# 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 for Egresss & Ingress rules
|
||||
"""
|
||||
#Import Local Modules
|
||||
import marvin
|
||||
from nose.plugins.attrib import attr
|
||||
from marvin.cloudstackTestCase import *
|
||||
from marvin.cloudstackAPI import *
|
||||
from marvin.remoteSSHClient import remoteSSHClient
|
||||
from marvin.integration.lib.utils import *
|
||||
from marvin.integration.lib.base import *
|
||||
from marvin.integration.lib.common import *
|
||||
|
||||
#Import System modules
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
|
||||
class Services:
|
||||
"""Test Security groups Services
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.services = {
|
||||
"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",
|
||||
},
|
||||
"virtual_machine": {
|
||||
# Create a small virtual machine instance with disk offering
|
||||
"displayname": "Test VM",
|
||||
"username": "root", # VM creds for SSH
|
||||
"password": "password",
|
||||
"ssh_port": 22,
|
||||
"hypervisor": 'XenServer',
|
||||
"privateport": 22,
|
||||
"publicport": 22,
|
||||
"protocol": 'TCP',
|
||||
"userdata": 'This is sample data',
|
||||
},
|
||||
"service_offering": {
|
||||
"name": "Tiny Instance",
|
||||
"displaytext": "Tiny Instance",
|
||||
"cpunumber": 1,
|
||||
"cpuspeed": 100, # in MHz
|
||||
"memory": 128, # In MBs
|
||||
},
|
||||
"security_group": {
|
||||
"name": 'SSH',
|
||||
"protocol": 'TCP',
|
||||
"startport": 22,
|
||||
"endport": 22,
|
||||
"cidrlist": '0.0.0.0/0',
|
||||
},
|
||||
"ostype": 'CentOS 5.3 (64-bit)',
|
||||
# CentOS 5.3 (64-bit)
|
||||
"sleep": 60,
|
||||
"timeout": 10,
|
||||
}
|
||||
|
||||
|
||||
class TestEgressAfterHostMaintenance(cloudstackTestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
||||
self.apiclient = self.testClient.getApiClient()
|
||||
self.dbclient = self.testClient.getDbConnection()
|
||||
self.cleanup = []
|
||||
return
|
||||
|
||||
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
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.services = Services().services
|
||||
cls.api_client = super(
|
||||
TestEgressAfterHostMaintenance,
|
||||
cls
|
||||
).getClsTestClient().getApiClient()
|
||||
|
||||
# Get Zone, Domain and templates
|
||||
cls.domain = get_domain(cls.api_client, cls.services)
|
||||
cls.zone = get_zone(cls.api_client, cls.services)
|
||||
cls.services['mode'] = cls.zone.networktype
|
||||
cls.pod = get_pod(
|
||||
cls.api_client,
|
||||
zoneid=cls.zone.id
|
||||
)
|
||||
|
||||
template = get_template(
|
||||
cls.api_client,
|
||||
cls.zone.id,
|
||||
cls.services["ostype"]
|
||||
)
|
||||
cls.services["domainid"] = cls.domain.id
|
||||
cls.services["virtual_machine"]["zoneid"] = cls.zone.id
|
||||
cls.services["virtual_machine"]["template"] = template.id
|
||||
|
||||
cls.service_offering = ServiceOffering.create(
|
||||
cls.api_client,
|
||||
cls.services["service_offering"]
|
||||
)
|
||||
cls.account = Account.create(
|
||||
cls.api_client,
|
||||
cls.services["account"],
|
||||
domainid=cls.domain.id
|
||||
)
|
||||
cls.services["account"] = cls.account.name
|
||||
cls._cleanup = [
|
||||
cls.account,
|
||||
cls.service_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
|
||||
|
||||
@attr(speed = "slow")
|
||||
@attr(tags = ["sg", "eip", "maintenance"])
|
||||
def test_egress_after_host_maintenance(self):
|
||||
"""Test maintenance case for egress
|
||||
"""
|
||||
|
||||
# Validate the following:
|
||||
# 1. createaccount of type user
|
||||
# 2. createsecuritygroup (ssh) for this account
|
||||
# 3. authorizeSecurityGroupIngress to allow ssh access to the VM
|
||||
# 4. authorizeSecurityGroupEgress to allow ssh access only out to
|
||||
# CIDR: 0.0.0.0/0
|
||||
# 5. deployVirtualMachine into this security group (ssh)
|
||||
# 6. deployed VM should be Running, ssh should be allowed into the VM
|
||||
# 7. Enable maintenance mode for host, cance maintenance mode
|
||||
# 8. User should be able to SSH into VM after maintainace
|
||||
|
||||
security_group = SecurityGroup.create(
|
||||
self.apiclient,
|
||||
self.services["security_group"],
|
||||
account=self.account.name,
|
||||
domainid=self.account.domainid
|
||||
)
|
||||
self.debug("Created security group with ID: %s" % security_group.id)
|
||||
|
||||
# Default Security group should not have any ingress rule
|
||||
sercurity_groups = SecurityGroup.list(
|
||||
self.apiclient,
|
||||
account=self.account.name,
|
||||
domainid=self.account.domainid
|
||||
)
|
||||
self.assertEqual(
|
||||
isinstance(sercurity_groups, list),
|
||||
True,
|
||||
"Check for list security groups response"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
len(sercurity_groups),
|
||||
2,
|
||||
"Check List Security groups response"
|
||||
)
|
||||
# Authorize Security group to SSH to VM
|
||||
self.debug(
|
||||
"Authorizing ingress rule for sec group ID: %s for ssh access"
|
||||
% security_group.id)
|
||||
ingress_rule = security_group.authorize(
|
||||
self.apiclient,
|
||||
self.services["security_group"],
|
||||
account=self.account.name,
|
||||
domainid=self.account.domainid
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
isinstance(ingress_rule, dict),
|
||||
True,
|
||||
"Check ingress rule created properly"
|
||||
)
|
||||
|
||||
ssh_rule = (ingress_rule["ingressrule"][0]).__dict__
|
||||
|
||||
# Authorize Security group to SSH to VM
|
||||
self.debug(
|
||||
"Authorizing egress rule for sec group ID: %s for ssh access"
|
||||
% security_group.id)
|
||||
egress_rule = security_group.authorizeEgress(
|
||||
self.apiclient,
|
||||
self.services["security_group"],
|
||||
account=self.account.name,
|
||||
domainid=self.account.domainid
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
isinstance(egress_rule, dict),
|
||||
True,
|
||||
"Check egress rule created properly"
|
||||
)
|
||||
ssh_egress_rule = (egress_rule["egressrule"][0]).__dict__
|
||||
|
||||
self.virtual_machine = VirtualMachine.create(
|
||||
self.apiclient,
|
||||
self.services["virtual_machine"],
|
||||
accountid=self.account.name,
|
||||
domainid=self.account.domainid,
|
||||
serviceofferingid=self.service_offering.id,
|
||||
securitygroupids=[security_group.id]
|
||||
)
|
||||
self.debug("Deploying VM in account: %s" % self.account.name)
|
||||
|
||||
# Should be able to SSH VM
|
||||
try:
|
||||
self.debug("SSH into VM: %s" % self.virtual_machine.id)
|
||||
ssh = self.virtual_machine.get_ssh_client()
|
||||
except Exception as e:
|
||||
self.fail("SSH Access failed for %s: %s" % \
|
||||
(self.virtual_machine.ipaddress, e)
|
||||
)
|
||||
vms = VirtualMachine.list(
|
||||
self.apiclient,
|
||||
id=self.virtual_machine.id,
|
||||
listall=True
|
||||
)
|
||||
self.assertEqual(
|
||||
isinstance(vms, list),
|
||||
True,
|
||||
"Check list VMs response for valid host"
|
||||
)
|
||||
vm = vms[0]
|
||||
|
||||
self.debug("Enabling host maintenance for ID: %s" % vm.hostid)
|
||||
cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd()
|
||||
cmd.id = vm.hostid
|
||||
self.apiclient.prepareHostForMaintenance(cmd)
|
||||
|
||||
self.debug("Canceling host maintenance for ID: %s" % vm.hostid)
|
||||
cmd = cancelHostMaintenance.cancelHostMaintenanceCmd()
|
||||
cmd.id = vm.hostid
|
||||
self.apiclient.cancelHostMaintenance(cmd)
|
||||
|
||||
self.debug("Waiting for SSVMs to come up")
|
||||
wait_for_ssvms(
|
||||
self.apiclient,
|
||||
zoneid=self.zone.id,
|
||||
podid=self.pod.id,
|
||||
)
|
||||
self.debug("Starting VM: %s" % self.virtual_machine.id)
|
||||
|
||||
self.virtual_machine.start(self.apiclient)
|
||||
# Should be able to SSH VM
|
||||
try:
|
||||
self.debug("SSH into VM: %s" % self.virtual_machine.id)
|
||||
ssh = self.virtual_machine.get_ssh_client(reconnect=True)
|
||||
except Exception as e:
|
||||
self.fail("SSH Access failed for %s: %s" % \
|
||||
(self.virtual_machine.ipaddress, e)
|
||||
)
|
||||
return
|
||||
|
|
@ -616,7 +616,7 @@ class TestHostHighAvailability(cloudstackTestCase):
|
|||
"The virtual machine is not ha enabled so check if VM is created on host which is also not ha enabled"
|
||||
)
|
||||
|
||||
#put the Host in maintainance mode
|
||||
#put the Host in maintenance mode
|
||||
self.debug("Enabling maintenance mode for host %s" % vm_with_ha_enabled.hostid)
|
||||
cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd()
|
||||
cmd.id = vm_with_ha_enabled.hostid
|
||||
|
|
@ -748,7 +748,7 @@ class TestHostHighAvailability(cloudstackTestCase):
|
|||
"The virtual machine is not ha enabled so check if VM is created on host which is also not ha enabled"
|
||||
)
|
||||
|
||||
#put the Host in maintainance mode
|
||||
#put the Host in maintenance mode
|
||||
self.debug("Enabling maintenance mode for host %s" % vm_with_ha_disabled.hostid)
|
||||
cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd()
|
||||
cmd.id = vm_with_ha_disabled.hostid
|
||||
|
|
|
|||
|
|
@ -0,0 +1,337 @@
|
|||
# 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.
|
||||
""" Tests for Multiple IP Ranges feature
|
||||
"""
|
||||
from marvin.cloudstackTestCase import *
|
||||
from marvin.cloudstackAPI import *
|
||||
from marvin.cloudstackException import cloudstackAPIException
|
||||
from marvin.integration.lib.utils import *
|
||||
from marvin.integration.lib.base import *
|
||||
from marvin.integration.lib.common import *
|
||||
#from netaddr import *
|
||||
import netaddr
|
||||
|
||||
from nose.plugins.attrib import attr
|
||||
|
||||
class Services:
|
||||
"""Test Multiple IP Ranges
|
||||
"""
|
||||
def __init__(self):
|
||||
self.services = {
|
||||
"account": {
|
||||
"email": "test@test.com",
|
||||
"firstname": "Test",
|
||||
"lastname": "User",
|
||||
"username": "test",
|
||||
# Random characters are appended for unique
|
||||
# username
|
||||
"password": "password",
|
||||
},
|
||||
"service_offering": {
|
||||
"name": "Tiny Instance",
|
||||
"displaytext": "Tiny Instance",
|
||||
"cpunumber": 1,
|
||||
"cpuspeed": 200, # in MHz
|
||||
"memory": 256, # In MBs
|
||||
},
|
||||
"disk_offering": {
|
||||
"displaytext": "Small Disk",
|
||||
"name": "Small Disk",
|
||||
"disksize": 1
|
||||
},
|
||||
"templates": {
|
||||
"displaytext": 'Template',
|
||||
"name": 'Template',
|
||||
"ostype": "CentOS 5.3 (64-bit)",
|
||||
"templatefilter": 'self',
|
||||
},
|
||||
"vlan_ip_range": {
|
||||
"startip": "",
|
||||
"endip": "",
|
||||
"netmask": "",
|
||||
"gateway": "",
|
||||
"forvirtualnetwork": "false",
|
||||
"vlan": "untagged",
|
||||
},
|
||||
"server_without_disk": {
|
||||
"displayname": "Test VM-No Disk",
|
||||
"username": "root",
|
||||
"password": "password",
|
||||
"hypervisor": 'XenServer',
|
||||
},
|
||||
"cidr": {
|
||||
"name": "cidr1 -Test",
|
||||
"gateway" :"10.147.43.1",
|
||||
"netmask" :"255.255.255.128",
|
||||
"startip" :"10.147.43.3",
|
||||
"endip" :"10.147.43.10",
|
||||
},
|
||||
"ostype": "CentOS 5.3 (64-bit)",
|
||||
"sleep": 60,
|
||||
"timeout": 10,
|
||||
}
|
||||
|
||||
class TestMultipleIpRanges(cloudstackTestCase):
|
||||
"""Test Multiple IP Ranges for guest network
|
||||
"""
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.api_client = super(TestMultipleIpRanges, cls).getClsTestClient().getApiClient()
|
||||
cls.services = Services().services
|
||||
# Get Zone, Domain and templates
|
||||
cls.domain = get_domain(cls.api_client, cls.services)
|
||||
cls.zone = get_zone(cls.api_client, cls.services)
|
||||
cls.pod = get_pod(cls.api_client, cls.zone.id, cls.services)
|
||||
cls.services['mode'] = cls.zone.networktype
|
||||
cls.services["domainid"] = cls.domain.id
|
||||
cls.services["zoneid"] = cls.zone.id
|
||||
cls.account = Account.create(
|
||||
cls.api_client,
|
||||
cls.services["account"],
|
||||
domainid=cls.domain.id
|
||||
)
|
||||
cls.services["account"] = cls.account.name
|
||||
cls.disk_offering = DiskOffering.create(
|
||||
cls.api_client,
|
||||
cls.services["disk_offering"]
|
||||
)
|
||||
cls.service_offering = ServiceOffering.create(
|
||||
cls.api_client,
|
||||
cls.services["service_offering"]
|
||||
)
|
||||
cls.template = get_template(
|
||||
cls.api_client,
|
||||
cls.zone.id,
|
||||
cls.services["ostype"]
|
||||
)
|
||||
cls.services["templates"]["ostypeid"] = cls.template.ostypeid
|
||||
cls.services["diskoffering"] = cls.disk_offering.id
|
||||
cls._cleanup = [
|
||||
cls.account,
|
||||
]
|
||||
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 = [ ]
|
||||
return
|
||||
|
||||
def tearDown(self):
|
||||
try:
|
||||
#Clean up, terminate the resources created
|
||||
cleanup_resources(self.apiclient, self.cleanup)
|
||||
except Exception as e:
|
||||
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||
return
|
||||
|
||||
def verify_vlan_range(self,vlan,services):
|
||||
#compare vlan_list response with configured values
|
||||
self.assertEqual(
|
||||
isinstance(vlan, list),
|
||||
True,
|
||||
"Check list response returned a valid list"
|
||||
)
|
||||
self.assertNotEqual(
|
||||
len(vlan),
|
||||
0,
|
||||
"check list vlan response"
|
||||
)
|
||||
self.assertEqual(
|
||||
str(vlan[0].startip),
|
||||
str(services["startip"]),
|
||||
"Start IP in vlan ip range is not matched with the configured start ip"
|
||||
)
|
||||
self.assertEqual(
|
||||
str(vlan[0].endip),
|
||||
str(services["endip"]),
|
||||
"End IP in vlan ip range is not matched with the configured end ip"
|
||||
)
|
||||
self.assertEqual(
|
||||
str(vlan[0].gateway),
|
||||
str(services["gateway"]),
|
||||
"gateway in vlan ip range is not matched with the configured gateway"
|
||||
)
|
||||
self.assertEqual(
|
||||
str(vlan[0].netmask),
|
||||
str(services["netmask"]),
|
||||
"netmask in vlan ip range is not matched with the configured netmask"
|
||||
)
|
||||
return
|
||||
|
||||
def list_Routers(self):
|
||||
"""Check if any VR is already present in the setup
|
||||
Will return True if yes else return False
|
||||
"""
|
||||
list_zone = Zone.list(self.apiclient)
|
||||
network_type = list_zone[0].networktype
|
||||
sg_enabled = list_zone[0].securitygroupsenabled
|
||||
if network_type == "Basic":
|
||||
vr_list = Router.list(self.apiclient, listall='true')
|
||||
self.debug("vr list {}".format(vr_list))
|
||||
if isinstance(vr_list,list) and len(vr_list) > 0:
|
||||
self.debug("VR is running in the setup")
|
||||
return True
|
||||
else:
|
||||
self.debug("VR is not present in the setup")
|
||||
return False
|
||||
elif network_type == "Advanced" and sg_enabled == True:
|
||||
nw_list = Network.list(
|
||||
self.apiclient,
|
||||
supportedservices='SecurityGroup',
|
||||
)
|
||||
nw_id = nw_list[0].id
|
||||
vr_list = Router.list(
|
||||
self.apiclient,
|
||||
networkid = nw_id,
|
||||
listall = 'true',
|
||||
)
|
||||
if isinstance(vr_list, list) and len(vr_list) > 0:
|
||||
self.debug("VR is present in the setup")
|
||||
return True
|
||||
else :
|
||||
self.debug("VR is not present in the setup")
|
||||
return False
|
||||
else :
|
||||
self.debug("Network type is not shared")
|
||||
return None
|
||||
|
||||
def test_01_deploy_vm_in_new_cidr(self):
|
||||
"""Deploy guest vm after adding guest IP range in new CIDR
|
||||
|
||||
1.Add IP range in new CIDR
|
||||
2.Deploy guest vm
|
||||
"""
|
||||
dc_id = self.dbclient.execute(
|
||||
"select id from data_center where uuid = '%s';" % str(self.services["zoneid"])
|
||||
)
|
||||
dc_id = dc_id[0][0]
|
||||
id_list = self.dbclient.execute(
|
||||
"select id from user_ip_address where allocated is null and data_center_id = '%s';" % str(dc_id)
|
||||
)
|
||||
ip_list = []
|
||||
for i in range(len(id_list)):
|
||||
ip_list.append(id_list[i][0])
|
||||
#Check if VR is already present in the setup
|
||||
vr_state = self.list_Routers();
|
||||
if vr_state is True :
|
||||
for id in ip_list:
|
||||
self.dbclient.execute(
|
||||
"update user_ip_address set allocated=now() where id = '%s';" % str(id)
|
||||
)
|
||||
else :
|
||||
ip_list = ip_list[:-2]
|
||||
for id in ip_list:
|
||||
self.dbclient.execute(
|
||||
"update user_ip_address set allocated=now() where id = '%s';" % str(id)
|
||||
)
|
||||
#Add IP range in the new CIDR
|
||||
test_gateway = self.services["cidr"]["gateway"]
|
||||
test_startIp = self.services["cidr"]["startip"]
|
||||
test_endIp = self.services["cidr"]["endip"]
|
||||
test_netmask = self.services["cidr"]["netmask"]
|
||||
#Populating services with new IP range
|
||||
self.services["vlan_ip_range"]["startip"] = test_startIp
|
||||
self.services["vlan_ip_range"]["endip"] = test_endIp
|
||||
self.services["vlan_ip_range"]["gateway"] = test_gateway
|
||||
self.services["vlan_ip_range"]["netmask"] = test_netmask
|
||||
self.services["vlan_ip_range"]["zoneid"] = self.zone.id
|
||||
self.services["vlan_ip_range"]["podid"] = self.pod.id
|
||||
#create new vlan ip range
|
||||
new_vlan = PublicIpRange.create(self.apiclient, self.services["vlan_ip_range"])
|
||||
self.debug("Created new vlan range with startip:%s and endip:%s" %(test_startIp,test_endIp))
|
||||
self.cleanup.append(new_vlan)
|
||||
new_vlan_res = new_vlan.list(self.apiclient,id=new_vlan.vlan.id)
|
||||
#Compare list output with configured values
|
||||
self.verify_vlan_range(new_vlan_res,self.services["vlan_ip_range"])
|
||||
#Deploy vm in existing subnet if VR is not present
|
||||
if vr_state is False :
|
||||
vm_res = VirtualMachine.create(
|
||||
self.apiclient,
|
||||
self.services["server_without_disk"],
|
||||
templateid = self.template.id,
|
||||
accountid = self.account.name,
|
||||
domainid = self.services["domainid"],
|
||||
zoneid = self.services["zoneid"],
|
||||
serviceofferingid = self.service_offering.id,
|
||||
mode = self.services["mode"],
|
||||
)
|
||||
self.cleanup.append(vm_res)
|
||||
#Deploy guest vm
|
||||
try :
|
||||
self.virtual_machine = VirtualMachine.create(
|
||||
self.apiclient,
|
||||
self.services["server_without_disk"],
|
||||
templateid = self.template.id,
|
||||
accountid = self.account.name,
|
||||
domainid = self.services["domainid"],
|
||||
zoneid = self.services["zoneid"],
|
||||
serviceofferingid = self.service_offering.id,
|
||||
mode = self.services["mode"],
|
||||
)
|
||||
except Exception as e :
|
||||
raise Exception("Warning: Exception during vm deployment: {}".format(e))
|
||||
finally :
|
||||
#Mark ip_Adddresses allocated state to Null which were marked as allocated at the beginning of the test
|
||||
for id in ip_list :
|
||||
self.dbclient.execute(
|
||||
"update user_ip_address set allocated=default where id = '%s';" % str(id)
|
||||
)
|
||||
self.vm_response = VirtualMachine.list(
|
||||
self.apiclient,
|
||||
id = self.virtual_machine.id
|
||||
)
|
||||
self.assertEqual(
|
||||
isinstance(self.vm_response, list),
|
||||
True,
|
||||
"Check VM list response returned a valid list"
|
||||
)
|
||||
self.ip_range = list(netaddr.iter_iprange(unicode(self.services["cidr"]["startip"]), unicode(self.services["cidr"]["endip"])))
|
||||
self.nic_ip = netaddr.IPAddress(unicode(self.vm_response[0].nic[0].ipaddress))
|
||||
self.debug("vm got {} as ip address".format(self.nic_ip))
|
||||
self.assertIn(
|
||||
self.nic_ip,
|
||||
self.ip_range,
|
||||
"VM did not get the ip address from the new ip range"
|
||||
)
|
||||
self.virtual_machine.delete(self.apiclient)
|
||||
expunge_del = Configurations.list(
|
||||
self.apiclient,
|
||||
name = 'expunge.delay'
|
||||
)
|
||||
expunge_int = Configurations.list(
|
||||
self.apiclient,
|
||||
name = 'expunge.interval'
|
||||
)
|
||||
wait_time = int(expunge_del[0].value) + int(expunge_int[0].value) + int(30)
|
||||
|
||||
self.debug("Waiting for {} seconds for the vm to expunge".format(wait_time))
|
||||
#wait for the vm to expunge
|
||||
time.sleep(wait_time)
|
||||
return
|
||||
|
||||
|
|
@ -30,8 +30,7 @@ from marvin.integration.lib.common import (get_domain,
|
|||
get_zone,
|
||||
get_template,
|
||||
cleanup_resources,
|
||||
wait_for_cleanup,
|
||||
get_updated_resource_count,
|
||||
wait_for_cleanup,
|
||||
find_suitable_host,
|
||||
get_resource_type
|
||||
)
|
||||
|
|
@ -97,7 +96,7 @@ class TestDomainMemoryLimits(cloudstackTestCase):
|
|||
# Get Zone, Domain and templates
|
||||
cls.domain = get_domain(cls.api_client, cls.services)
|
||||
cls.zone = get_zone(cls.api_client, cls.services)
|
||||
cls.services["mode"] = cls.zone.networktype
|
||||
cls.services["mode"] = cls.zone.networktype
|
||||
|
||||
cls.template = get_template(
|
||||
cls.api_client,
|
||||
|
|
@ -127,7 +126,7 @@ class TestDomainMemoryLimits(cloudstackTestCase):
|
|||
def setUp(self):
|
||||
self.apiclient = self.testClient.getApiClient()
|
||||
self.dbclient = self.testClient.getDbConnection()
|
||||
|
||||
|
||||
self.cleanup = []
|
||||
return
|
||||
|
||||
|
|
@ -144,8 +143,8 @@ class TestDomainMemoryLimits(cloudstackTestCase):
|
|||
self.debug("Deploying an instance in account: %s" %
|
||||
self.account.name)
|
||||
|
||||
if api_client is None:
|
||||
api_client = self.apiclient
|
||||
if api_client is None:
|
||||
api_client = self.apiclient
|
||||
try:
|
||||
vm = VirtualMachine.create(
|
||||
api_client,
|
||||
|
|
@ -163,63 +162,60 @@ class TestDomainMemoryLimits(cloudstackTestCase):
|
|||
"Vm state should be running after deployment")
|
||||
return vm
|
||||
except Exception as e:
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
|
||||
def setupAccounts(self):
|
||||
|
||||
self.debug("Creating a sub-domain under: %s" % self.domain.name)
|
||||
self.child_domain = Domain.create(self.apiclient,
|
||||
self.child_domain_1 = Domain.create(self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.domain.id)
|
||||
self.child_do_admin = Account.create(
|
||||
self.child_do_admin_1 = Account.create(
|
||||
self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True,
|
||||
domainid=self.child_domain.id
|
||||
domainid=self.child_domain_1.id
|
||||
)
|
||||
# Cleanup the resources created at end of test
|
||||
self.cleanup.append(self.child_do_admin)
|
||||
self.cleanup.append(self.child_domain)
|
||||
self.cleanup.append(self.child_do_admin_1)
|
||||
self.cleanup.append(self.child_domain_1)
|
||||
|
||||
Resources.updateLimit(self.apiclient,
|
||||
resourcetype=9,
|
||||
max=5120,
|
||||
account=self.child_do_admin.name,
|
||||
domainid=self.child_do_admin.domainid)
|
||||
|
||||
self.domain = Domain.create(self.apiclient,
|
||||
max=15360,
|
||||
account=self.child_do_admin_1.name,
|
||||
domainid=self.child_do_admin_1.domainid)
|
||||
|
||||
self.child_domain_2 = Domain.create(self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.domain.id)
|
||||
|
||||
self.admin = Account.create(
|
||||
self.child_do_admin_2 = Account.create(
|
||||
self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True,
|
||||
domainid=self.domain.id)
|
||||
|
||||
domainid=self.child_domain_2.id)
|
||||
|
||||
# Cleanup the resources created at end of test
|
||||
self.cleanup.append(self.admin)
|
||||
self.cleanup.append(self.domain)
|
||||
self.cleanup.append(self.child_do_admin_2)
|
||||
self.cleanup.append(self.child_domain_2)
|
||||
|
||||
Resources.updateLimit(self.apiclient,
|
||||
resourcetype=9,
|
||||
max=5120,
|
||||
account=self.admin.name,
|
||||
domainid=self.admin.domainid)
|
||||
max=15360,
|
||||
account=self.child_do_admin_2.name,
|
||||
domainid=self.child_do_admin_2.domainid)
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(configuration='max.account.memory')
|
||||
def test_01_change_service_offering(self):
|
||||
"""Test Deploy VM with 5 GB RAM & verify the usage"""
|
||||
#Keep max account memory (configuration) as 5 GB
|
||||
|
||||
# Validate the following
|
||||
# 1. Create compute offering with 5 GB RAM & Deploy VM in the created domain
|
||||
# 2. Update Resource count for the root admin Memory usage
|
||||
# 2. List Resource count for the root admin Memory usage
|
||||
# 3. Upgrade and downgrade service offering
|
||||
# 4. Resource count should list properly for the domain
|
||||
|
||||
#Keep max account memory (configuration) as 5 GB
|
||||
# 4. Resource count should list properly for the domain
|
||||
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts()
|
||||
|
|
@ -232,21 +228,38 @@ class TestDomainMemoryLimits(cloudstackTestCase):
|
|||
self.debug("Creating an instance with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
|
||||
|
||||
vm = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].memorytotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["memory"])
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Resource count should match with the expected resource count")
|
||||
|
||||
self.debug("Stopping instance: %s" % vm.name)
|
||||
try:
|
||||
vm.stop(self.apiclient)
|
||||
except Exception as e:
|
||||
self.fail("Failed to stop instance: %s" % e)
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_stop = account_list[0].memorytotal
|
||||
|
||||
self.asserEqual(resource_count_after_stop, expected_resource_count,
|
||||
"Resource count should be same after stopping the instance")
|
||||
|
||||
self.debug("Creating service offering with 7 GB RAM")
|
||||
self.services["service_offering"]["memory"] = 7168
|
||||
|
|
@ -269,8 +282,18 @@ class TestDomainMemoryLimits(cloudstackTestCase):
|
|||
except Exception as e:
|
||||
self.fail("Failed to change service offering of vm %s - %s" %
|
||||
(vm.name, e))
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_upgrade = account_list[0].memorytotal
|
||||
|
||||
self.debug(resource_count_after_upgrade)
|
||||
|
||||
self.assertTrue(resource_count_after_upgrade > resource_count_after_stop,
|
||||
"Resource count should be more than before, after upgrading service offering")
|
||||
|
||||
self.debug(
|
||||
"Down grade service offering of instance %s from %s to %s" %
|
||||
|
|
@ -284,30 +307,43 @@ class TestDomainMemoryLimits(cloudstackTestCase):
|
|||
except Exception as e:
|
||||
self.fail("Failed to change service offering of vm %s - %s" %
|
||||
(vm.name, e))
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_downgrade = account_list[0].memorytotal
|
||||
|
||||
self.assertTrue(resource_count_after_downgrade < resource_count_after_upgrade,
|
||||
"Resource count should be less than before, after downgrading service offering")
|
||||
|
||||
self.debug("Starting instance: %s" % vm.name)
|
||||
try:
|
||||
vm.start(self.apiclient)
|
||||
except Exception as e:
|
||||
self.fail("Failed to start instance: %s" % e)
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_start = account_list[0].memorytotal
|
||||
|
||||
self.assertTrue(resource_count_after_start == resource_count_after_downgrade,
|
||||
"Resource count should be same after starting the instance")
|
||||
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(configuration='max.account.memory')
|
||||
def test_02_migrate_vm(self):
|
||||
"""Test Deploy VM with 5 GB RAM & verify the usage"""
|
||||
#Keep max account memory (configuration) as 5 GB
|
||||
|
||||
# Validate the following
|
||||
# 1. Create compute offering with 5 GB RAM & Deploy VM in the created domain
|
||||
# 2. Update Resource count for the root admin Memory usage
|
||||
# 2. List Resource count for the root admin Memory usage
|
||||
# 3. Migrate vm to another host, resource count should list properly.
|
||||
|
||||
#Keep max account memory (configuration) as 5 GB
|
||||
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts()
|
||||
users = { self.domain: self.admin,
|
||||
|
|
@ -319,14 +355,23 @@ class TestDomainMemoryLimits(cloudstackTestCase):
|
|||
self.debug("Creating an instance with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
|
||||
|
||||
vm = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].memorytotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["memory"])
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Resource count should match with the expected resource count")
|
||||
|
||||
host = find_suitable_host(self.apiclient, vm)
|
||||
self.debug("Migrating instance: %s to host: %s" %
|
||||
|
|
@ -335,21 +380,25 @@ class TestDomainMemoryLimits(cloudstackTestCase):
|
|||
vm.migrate(self.apiclient, host.id)
|
||||
except Exception as e:
|
||||
self.fail("Failed to migrate instance: %s" % e)
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_migrate = account_list[0].memorytotal
|
||||
|
||||
self.assertTrue(resource_count_after_migrate == resource_count,
|
||||
"Resource count should be same after migrating the instance")
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(configuration='max.account.memory')
|
||||
def test_03_delete_vm(self):
|
||||
"""Test Deploy VM with 5 GB RAM & verify the usage"""
|
||||
#Keep max account memory (configuration) as 5 GB
|
||||
|
||||
# Validate the following
|
||||
# 1. Create compute offering with 5 GB RAM & Deploy VM in the created domain
|
||||
# 2. Update Resource count for the root admin Memory usage
|
||||
# 2. List Resource count for the root admin Memory usage
|
||||
# 3. Delete vm, resource count should list as 0 after delete operation.
|
||||
|
||||
#Keep max account memory (configuration) as 5 GB
|
||||
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts()
|
||||
|
|
@ -362,14 +411,23 @@ class TestDomainMemoryLimits(cloudstackTestCase):
|
|||
self.debug("Creating an instance with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
|
||||
|
||||
vm = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].memorytotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["memory"])
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Resource count should match with the expected resource count")
|
||||
|
||||
self.debug("Destroying instance: %s" % vm.name)
|
||||
try:
|
||||
|
|
@ -377,23 +435,26 @@ class TestDomainMemoryLimits(cloudstackTestCase):
|
|||
except Exception as e:
|
||||
self.fail("Failed to delete instance: %s" % e)
|
||||
|
||||
# Wait for expunge interval to cleanup Memory
|
||||
wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"])
|
||||
# Wait for expunge interval to cleanup Memory
|
||||
wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"])
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
self.assertEqual(resource_count, 0 , "Resource count for %s should be 0" % get_resource_type(resource_id=9))#RAM
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_delete = account_list[0].memorytotal
|
||||
self.assertEqual(resource_count_after_delete, 0 , "Resource count for %s should be 0" % get_resource_type(resource_id=9))#RAM
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(configuration='max.account.memory')
|
||||
def test_04_deploy_multiple_vm(self):
|
||||
"""Test Deploy multiple VM with 5 GB RAM & verify the usage"""
|
||||
#Keep max account memory (configuration) as 5 GB
|
||||
|
||||
# Validate the following
|
||||
# 1. Create compute offering with 5 GB RAM
|
||||
# 2. Deploy multiple VMs with this service offering
|
||||
# 3. Update Resource count for the root admin Memory usage
|
||||
# 3. List Resource count for the root admin Memory usage
|
||||
# 4. Memory usage should list properly
|
||||
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
|
|
@ -407,39 +468,32 @@ class TestDomainMemoryLimits(cloudstackTestCase):
|
|||
self.debug("Creating an instance with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
|
||||
vm_1 = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
vm_2 = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
vm_3 = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
vm_3 = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
|
||||
self.debug("Deploying instance - Memory capacity is fully utilized")
|
||||
with self.assertRaises(Exception):
|
||||
self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
self.debug("Destroying instance: %s" % vm_1.name)
|
||||
try:
|
||||
vm_1.delete(self.apiclient)
|
||||
except Exception as e:
|
||||
self.fail("Failed to delete instance: %s" % e)
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].memorytotal
|
||||
|
||||
host = find_suitable_host(self.apiclient, vm_2)
|
||||
self.debug("Migrating instance: %s to host: %s" % (vm_2.name,
|
||||
host.name))
|
||||
try:
|
||||
vm_2.migrate(self.apiclient, host.id)
|
||||
except Exception as e:
|
||||
self.fail("Failed to migrate instance: %s" % e)
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
vm_2.delete(self.apiclient)
|
||||
vm_3.delete(self.apiclient)
|
||||
expected_resource_count = int(self.services["service_offering"]["memory"]) * 3 #Total 3 VMs
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Resource count should match with the expected resource count")
|
||||
|
||||
vm_2.delete(self.apiclient)
|
||||
vm_3.delete(self.apiclient)
|
||||
return
|
||||
|
||||
|
||||
|
|
@ -514,7 +568,7 @@ class TestMultipleChildDomainsMemory(cloudstackTestCase):
|
|||
"Vm state should be running after deployment")
|
||||
return vm
|
||||
except Exception as e:
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
|
||||
def setupAccounts(self):
|
||||
|
||||
|
|
@ -528,7 +582,7 @@ class TestMultipleChildDomainsMemory(cloudstackTestCase):
|
|||
admin=True,
|
||||
domainid=self.domain.id
|
||||
)
|
||||
|
||||
|
||||
self.debug("Updating the Memory resource count for domain: %s" %
|
||||
self.domain.name)
|
||||
Resources.updateLimit(self.apiclient,
|
||||
|
|
@ -552,12 +606,12 @@ class TestMultipleChildDomainsMemory(cloudstackTestCase):
|
|||
admin=True,
|
||||
domainid=self.cdomain_1.id
|
||||
)
|
||||
|
||||
|
||||
self.debug("Updating the Memory resource count for domain: %s" %
|
||||
self.cdomain_1.name)
|
||||
Resources.updateLimit(self.apiclient,
|
||||
resourcetype=9,
|
||||
max=5120,
|
||||
max=5120,
|
||||
domainid=self.cadmin_1.domainid)
|
||||
|
||||
self.debug("Updating the Memory resource count for account: %s" %
|
||||
|
|
@ -579,7 +633,7 @@ class TestMultipleChildDomainsMemory(cloudstackTestCase):
|
|||
self.cdomain_2.name)
|
||||
Resources.updateLimit(self.apiclient,
|
||||
resourcetype=9,
|
||||
max=5120,
|
||||
max=5120,
|
||||
domainid=self.cadmin_2.domainid)
|
||||
|
||||
self.debug("Updating the Memory resource count for domain: %s" %
|
||||
|
|
@ -597,7 +651,7 @@ class TestMultipleChildDomainsMemory(cloudstackTestCase):
|
|||
self.cleanup.append(self.cdomain_2)
|
||||
self.cleanup.append(self.parentd_admin)
|
||||
self.cleanup.append(self.parent_domain)
|
||||
|
||||
|
||||
users = {
|
||||
self.parent_domain: self.parentd_admin,
|
||||
self.cdomain_1: self.cadmin_1,
|
||||
|
|
@ -649,10 +703,20 @@ class TestMultipleChildDomainsMemory(cloudstackTestCase):
|
|||
vm_2 = self.createInstance(account=self.cadmin_2,
|
||||
service_off=self.service_offering, api_client=api_client_cadmin_2)
|
||||
|
||||
resource_count_cadmin_1 = get_updated_resource_count(self.apiclient, account=self.cadmin_1, rtype=9)#RAM
|
||||
account_list = Account.list(self.apiclient, id=self.cadmin_1.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_cadmin_1 = account_list[0].memorytotal
|
||||
self.debug(resource_count_cadmin_1)
|
||||
|
||||
resource_count_cadmin_2 = get_updated_resource_count(self.apiclient, account=self.cadmin_2, rtype=9)#RAM
|
||||
account_list = Account.list(self.apiclient, id=self.cadmin_2.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_cadmin_2 = account_list[0].memorytotal
|
||||
self.debug(resource_count_cadmin_2)
|
||||
|
||||
self.debug(
|
||||
|
|
@ -664,8 +728,8 @@ class TestMultipleChildDomainsMemory(cloudstackTestCase):
|
|||
self.debug(
|
||||
"Creating instance when Memory limit is fully used in child domain")
|
||||
with self.assertRaises(Exception):
|
||||
self.createInstance(account=self.cadmin_1,
|
||||
service_off=self.service_offering, api_client=api_client_cadmin_1)
|
||||
self.createInstance(account=self.cadmin_2,
|
||||
service_off=self.service_offering, api_client=api_client_cadmin_2)
|
||||
self.debug("Destroying instances: %s, %s" % (vm_1.name, vm_2.name))
|
||||
try:
|
||||
vm_1.delete(self.apiclient)
|
||||
|
|
@ -675,15 +739,23 @@ class TestMultipleChildDomainsMemory(cloudstackTestCase):
|
|||
|
||||
self.debug("Checking resource count for account: %s" % self.cadmin_1.name)
|
||||
|
||||
resource_count_cadmin_1 = get_updated_resource_count(self.apiclient, account=self.cadmin_1, rtype=9)#RAM
|
||||
self.debug(resource_count_cadmin_1)
|
||||
account_list = Account.list(self.apiclient, id=self.cadmin_1.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_cadmin_1 = account_list[0].memorytotal
|
||||
|
||||
self.assertEqual(resource_count_cadmin_1, 0 , "Resource count for %s should be 0" % get_resource_type(resource_id=9))#RAM
|
||||
|
||||
self.debug("Checking resource count for account: %s" % self.cadmin_2.name)
|
||||
|
||||
resource_count_cadmin_2 = get_updated_resource_count(self.apiclient, account=self.cadmin_2, rtype=9)#RAM
|
||||
self.debug(resource_count_cadmin_2)
|
||||
account_list = Account.list(self.apiclient, id=self.cadmin_1.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_cadmin_2 = account_list[0].memorytotal
|
||||
|
||||
self.assertEqual(resource_count_cadmin_2, 0 , "Resource count for %s should be 0" % get_resource_type(resource_id=9))#RAM
|
||||
return
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ class TestMaxMemoryLimits(cloudstackTestCase):
|
|||
# Get Zone, Domain and templates
|
||||
cls.domain = get_domain(cls.api_client, cls.services)
|
||||
cls.zone = get_zone(cls.api_client, cls.services)
|
||||
cls.services["mode"] = cls.zone.networktype
|
||||
cls.services["mode"] = cls.zone.networktype
|
||||
|
||||
cls.template = get_template(
|
||||
cls.api_client,
|
||||
|
|
@ -124,14 +124,14 @@ class TestMaxMemoryLimits(cloudstackTestCase):
|
|||
def setUp(self):
|
||||
self.apiclient = self.testClient.getApiClient()
|
||||
self.dbclient = self.testClient.getDbConnection()
|
||||
self.account = Account.create(
|
||||
self.account = Account.create(
|
||||
self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True
|
||||
)
|
||||
|
||||
self.debug("Creating service offering with 5 GB RAM")
|
||||
|
||||
|
||||
self.cleanup = [self.account, ]
|
||||
return
|
||||
|
||||
|
|
@ -149,27 +149,20 @@ class TestMaxMemoryLimits(cloudstackTestCase):
|
|||
self.debug("Deploying an instance in account: %s" %
|
||||
self.account.name)
|
||||
|
||||
if api_client is None:
|
||||
api_client = self.apiclient
|
||||
if api_client is None:
|
||||
api_client = self.apiclient
|
||||
|
||||
try:
|
||||
if account:
|
||||
vm = VirtualMachine.create(
|
||||
vm = VirtualMachine.create(
|
||||
api_client,
|
||||
self.services["virtual_machine"],
|
||||
templateid=self.template.id,
|
||||
accountid=account.name,
|
||||
domainid=account.domainid,
|
||||
networkids=networks,
|
||||
serviceofferingid=service_off.id)
|
||||
elif project:
|
||||
vm = VirtualMachine.create(
|
||||
api_client,
|
||||
self.services["virtual_machine"],
|
||||
templateid=self.template.id,
|
||||
projectid=project.id,
|
||||
accountid=account.name if account else None,
|
||||
domainid=account.domainid if account else None,
|
||||
projectid=project.id if project else None,
|
||||
networkids=networks,
|
||||
serviceofferingid=service_off.id)
|
||||
|
||||
vms = VirtualMachine.list(api_client, id=vm.id, listall=True)
|
||||
self.assertIsInstance(vms,
|
||||
list,
|
||||
|
|
@ -178,182 +171,182 @@ class TestMaxMemoryLimits(cloudstackTestCase):
|
|||
"Vm state should be running after deployment")
|
||||
return vm
|
||||
except Exception as e:
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
|
||||
def setupAccounts(self, account_limit=2, domain_limit=2, project_limit=2):
|
||||
|
||||
self.debug("Creating a domain under: %s" % self.domain.name)
|
||||
self.child_domain = Domain.create(self.apiclient,
|
||||
self.child_domain = Domain.create(self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.domain.id)
|
||||
|
||||
|
||||
self.debug("domain crated with domain id %s" % self.child_domain.id)
|
||||
self.debug("domain crated with domain id %s" % self.child_domain.id)
|
||||
|
||||
self.child_do_admin = Account.create(
|
||||
self.child_do_admin = Account.create(
|
||||
self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True,
|
||||
domainid=self.child_domain.id
|
||||
)
|
||||
|
||||
self.debug("domain admin created for domain id %s" %
|
||||
self.child_do_admin.domainid)
|
||||
self.debug("domain admin created for domain id %s" %
|
||||
self.child_do_admin.domainid)
|
||||
|
||||
# Create project as a domain admin
|
||||
self.project = Project.create(self.apiclient,
|
||||
# Create project as a domain admin
|
||||
self.project = Project.create(self.apiclient,
|
||||
self.services["project"],
|
||||
account=self.child_do_admin.name,
|
||||
domainid=self.child_do_admin.domainid)
|
||||
|
||||
# Cleanup created project at end of test
|
||||
self.cleanup.append(self.project)
|
||||
# Cleanup created project at end of test
|
||||
self.cleanup.append(self.project)
|
||||
|
||||
|
||||
# Cleanup accounts created
|
||||
self.cleanup.append(self.child_do_admin)
|
||||
self.cleanup.append(self.child_domain)
|
||||
# Cleanup accounts created
|
||||
self.cleanup.append(self.child_do_admin)
|
||||
self.cleanup.append(self.child_domain)
|
||||
|
||||
self.debug("Updating the Memory resource count for domain: %s" %
|
||||
self.debug("Updating the Memory resource count for domain: %s" %
|
||||
self.child_domain.name)
|
||||
# Update resource limits for account 1
|
||||
responses = Resources.updateLimit(self.apiclient,
|
||||
# Update resource limits for account 1
|
||||
responses = Resources.updateLimit(self.apiclient,
|
||||
resourcetype=9,
|
||||
max=(account_limit * 1024),
|
||||
account=self.child_do_admin.name,
|
||||
domainid=self.child_do_admin.domainid
|
||||
)
|
||||
|
||||
self.debug("Memory Resource count for child domain admin account is now: %s" %
|
||||
responses.max)
|
||||
self.debug("Memory Resource count for child domain admin account is now: %s" %
|
||||
responses.max)
|
||||
|
||||
# Update resource limits for project
|
||||
responses = Resources.updateLimit(self.apiclient,
|
||||
# Update resource limits for project
|
||||
responses = Resources.updateLimit(self.apiclient,
|
||||
resourcetype=9,
|
||||
max=(project_limit * 1024),
|
||||
projectid=self.project.id)
|
||||
|
||||
self.debug("Memory Resource count for project is now")
|
||||
self.debug(responses.max)
|
||||
self.debug("Memory Resource count for project is now")
|
||||
self.debug(responses.max)
|
||||
|
||||
# TODO: Update the Memory limit for domain only
|
||||
responses = Resources.updateLimit(self.apiclient,
|
||||
# TODO: Update the Memory limit for domain only
|
||||
responses = Resources.updateLimit(self.apiclient,
|
||||
resourcetype=9,
|
||||
max=(domain_limit * 1024),
|
||||
domainid=self.child_domain.id)
|
||||
|
||||
self.debug("Memory Resource count for domain %s with id %s is now %s" %
|
||||
(responses.domain, responses.domainid, responses.max))
|
||||
return
|
||||
|
||||
self.debug("Memory Resource count for domain %s with id %s is now %s" %
|
||||
(responses.domain, responses.domainid, responses.max))
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_01_deploy_vm_domain_limit_reached(self):
|
||||
"""Test Try to deploy VM with admin account where account has not used
|
||||
"""Test Try to deploy VM with admin account where account has not used
|
||||
the resources but @ domain they are not available"""
|
||||
|
||||
# Validate the following
|
||||
# 1. Try to deploy VM with admin account where account has not used the
|
||||
# resources but @ domain they are not available
|
||||
# 2. Deploy VM should error out saying ResourceAllocationException
|
||||
# with "resource limit exceeds"
|
||||
# Validate the following
|
||||
# 1. Try to deploy VM with admin account where account has not used the
|
||||
# resources but @ domain they are not available
|
||||
# 2. Deploy VM should error out saying ResourceAllocationException
|
||||
# with "resource limit exceeds"
|
||||
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts(account_limit=8, domain_limit=4)
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts(account_limit=8, domain_limit=4)
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.child_do_admin.name,
|
||||
DomainName=self.child_do_admin.domain)
|
||||
|
||||
self.debug("Creating instance with domain %s and admin account %s" %
|
||||
(self.child_do_admin.domainid,
|
||||
self.child_do_admin.name))
|
||||
self.debug("Creating instance with domain %s and admin account %s" %
|
||||
(self.child_do_admin.domainid,
|
||||
self.child_do_admin.name))
|
||||
|
||||
with self.assertRaises(Exception):
|
||||
self.createInstance(account=self.child_do_admin,
|
||||
with self.assertRaises(Exception):
|
||||
self.createInstance(account=self.child_do_admin,
|
||||
service_off=self.service_offering, api_client=api_client)
|
||||
return
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_02_deploy_vm_account_limit_reached(self):
|
||||
"""Test Try to deploy VM with admin account where account has used
|
||||
"""Test Try to deploy VM with admin account where account has used
|
||||
the resources but @ domain they are available"""
|
||||
|
||||
# Validate the following
|
||||
# 1. Try to deploy VM with admin account where account has used the
|
||||
# resources but @ domain they are available
|
||||
# 2. Deploy VM should error out saying ResourceAllocationException
|
||||
# with "resource limit exceeds"
|
||||
# Validate the following
|
||||
# 1. Try to deploy VM with admin account where account has used the
|
||||
# resources but @ domain they are available
|
||||
# 2. Deploy VM should error out saying ResourceAllocationException
|
||||
# with "resource limit exceeds"
|
||||
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts(account_limit=7, domain_limit=14)
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts(account_limit=7, domain_limit=14)
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.child_do_admin.name,
|
||||
DomainName=self.child_do_admin.domain)
|
||||
|
||||
self.debug("Deploying instance with account: %s" %
|
||||
self.debug("Deploying instance with account: %s" %
|
||||
self.child_do_admin.name)
|
||||
self.createInstance(account=self.child_do_admin,
|
||||
service_off=self.service_offering, api_client=api_client)
|
||||
|
||||
self.debug("Deploying instance in account 1 when Memory limit is reached")
|
||||
|
||||
with self.assertRaises(Exception):
|
||||
self.createInstance(account=self.child_do_admin,
|
||||
self.createInstance(account=self.child_do_admin,
|
||||
service_off=self.service_offering, api_client=api_client)
|
||||
return
|
||||
|
||||
self.debug("Deploying instance in account 1 when Memory limit is reached")
|
||||
|
||||
with self.assertRaises(Exception):
|
||||
self.createInstance(account=self.child_do_admin,
|
||||
service_off=self.service_offering, api_client=api_client)
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_03_deploy_vm_project_limit_reached(self):
|
||||
"""Test TTry to deploy VM with admin account where account has not used
|
||||
the resources but @ project they are not available"""
|
||||
"""Test TTry to deploy VM with admin account where account has not used
|
||||
the resources but @ project they are not available"""
|
||||
|
||||
# Validate the following
|
||||
# 1. Try to deploy VM with admin account where account has not used the
|
||||
# resources but @ project they are not available
|
||||
# 2. Deploy VM should error out saying ResourceAllocationException
|
||||
# with "resource limit exceeds"
|
||||
# Validate the following
|
||||
# 1. Try to deploy VM with admin account where account has not used the
|
||||
# resources but @ project they are not available
|
||||
# 2. Deploy VM should error out saying ResourceAllocationException
|
||||
# with "resource limit exceeds"
|
||||
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts(account_limit=8,domain_limit=8, project_limit=4)
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts(account_limit=8,domain_limit=8, project_limit=4)
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.child_do_admin.name,
|
||||
DomainName=self.child_do_admin.domain)
|
||||
|
||||
self.debug("Deploying instance with project: %s" % self.project.name)
|
||||
with self.assertRaises(Exception):
|
||||
self.createInstance(project = self.project,
|
||||
self.debug("Deploying instance with project: %s" % self.project.name)
|
||||
with self.assertRaises(Exception):
|
||||
self.createInstance(project = self.project,
|
||||
service_off=self.service_offering, api_client=api_client)
|
||||
return
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns"])
|
||||
def test_04_deployVm__account_limit_reached(self):
|
||||
"""Test Try to deploy VM with admin account where account has used
|
||||
"""Test Try to deploy VM with admin account where account has used
|
||||
the resources but @ project they are available"""
|
||||
|
||||
# Validate the following
|
||||
# 1. Try to deploy VM with admin account where account has used the
|
||||
# resources but @ project they are available
|
||||
# 2. Deploy VM should error out saying ResourceAllocationException
|
||||
# with "resource limit exceeds"
|
||||
# Validate the following
|
||||
# 1. Try to deploy VM with admin account where account has used the
|
||||
# resources but @ project they are available
|
||||
# 2. Deploy VM should error out saying ResourceAllocationException
|
||||
# with "resource limit exceeds"
|
||||
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts(account_limit=6, project_limit=12, domain_limit=12)
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts(account_limit=6, project_limit=12, domain_limit=12)
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.child_do_admin.name,
|
||||
DomainName=self.child_do_admin.domain)
|
||||
|
||||
self.debug("Deploying instance with account: %s" %
|
||||
self.debug("Deploying instance with account: %s" %
|
||||
self.child_do_admin.name)
|
||||
self.createInstance(account=self.child_do_admin,
|
||||
service_off=self.service_offering, api_client=api_client)
|
||||
self.createInstance(account=self.child_do_admin,
|
||||
service_off=self.service_offering, api_client=api_client)
|
||||
|
||||
self.debug("Deploying instance in account: %s when memory limit is reached" %
|
||||
self.debug("Deploying instance in account: %s when memory limit is reached" %
|
||||
self.child_do_admin.name)
|
||||
|
||||
with self.assertRaises(Exception):
|
||||
self.createInstance(project=self.project,
|
||||
with self.assertRaises(Exception):
|
||||
self.createInstance(project=self.project, account=self.child_do_admin,
|
||||
service_off=self.service_offering, api_client=api_client)
|
||||
return
|
||||
return
|
||||
|
|
|
|||
|
|
@ -31,9 +31,8 @@ from marvin.integration.lib.common import (get_domain,
|
|||
get_template,
|
||||
cleanup_resources,
|
||||
wait_for_cleanup,
|
||||
get_updated_resource_count,
|
||||
find_suitable_host,
|
||||
get_resource_type
|
||||
get_resource_type
|
||||
)
|
||||
|
||||
class Services:
|
||||
|
|
@ -97,7 +96,8 @@ class TestMemoryLimits(cloudstackTestCase):
|
|||
# Get Zone, Domain and templates
|
||||
cls.domain = get_domain(cls.api_client, cls.services)
|
||||
cls.zone = get_zone(cls.api_client, cls.services)
|
||||
cls.services["mode"] = cls.zone.networktype
|
||||
|
||||
cls.services["mode"] = cls.zone.networktype
|
||||
|
||||
cls.template = get_template(
|
||||
cls.api_client,
|
||||
|
|
@ -137,9 +137,6 @@ class TestMemoryLimits(cloudstackTestCase):
|
|||
self.service_offering.name)
|
||||
self.vm = self.createInstance(service_off=self.service_offering)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
|
||||
self.cleanup = [self.account, ]
|
||||
return
|
||||
|
||||
|
|
@ -156,8 +153,8 @@ class TestMemoryLimits(cloudstackTestCase):
|
|||
self.debug("Deploying an instance in account: %s" %
|
||||
self.account.name)
|
||||
|
||||
if api_client is None:
|
||||
api_client = self.apiclient
|
||||
if api_client is None:
|
||||
api_client = self.apiclient
|
||||
|
||||
try:
|
||||
vm = VirtualMachine.create(
|
||||
|
|
@ -176,61 +173,119 @@ class TestMemoryLimits(cloudstackTestCase):
|
|||
"Vm state should be running after deployment")
|
||||
return vm
|
||||
except Exception as e:
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_01_reboot_instance(self):
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_01_stop_start_instance(self):
|
||||
"""Test Deploy VM with 5 GB RAM & verify the usage"""
|
||||
|
||||
# Validate the following
|
||||
# 1. Create compute offering with 5 GB RAM & Deploy VM as root admin
|
||||
# 2. Update Resource count for the root admin Memory usage
|
||||
# 3. Stop and start instance, resource count should list properly.
|
||||
|
||||
# 2 .List Resource count for the root admin Memory usage
|
||||
# 3. Stop and start instance, resource count should list properly.
|
||||
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].memorytotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["memory"])
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Resource count should match with the expected resource count")
|
||||
|
||||
self.debug("Stopping instance: %s" % self.vm.name)
|
||||
try:
|
||||
self.vm.stop(self.apiclient)
|
||||
except Exception as e:
|
||||
self.fail("Failed to stop instance: %s" % e)
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_stop = account_list[0].memorytotal
|
||||
|
||||
self.assertEqual(resource_count, resource_count_after_stop,
|
||||
"Resource count should be same after stopping the instance")
|
||||
|
||||
self.debug("Starting instance: %s" % self.vm.name)
|
||||
try:
|
||||
self.vm.start(self.apiclient)
|
||||
except Exception as e:
|
||||
self.fail("Failed to start instance: %s" % e)
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_start = account_list[0].memorytotal
|
||||
|
||||
self.assertEqual(resource_count, resource_count_after_start,
|
||||
"Resource count should be same after stopping the instance")
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_02_migrate_instance(self):
|
||||
"""Test Deploy VM with 5 GB RAM & verify the usage"""
|
||||
|
||||
# Validate the following
|
||||
# 1. Create compute offering with 5 GB RAM & Deploy VM as root admin
|
||||
# 2. Update Resource count for the root admin Memory usage
|
||||
# 2. List Resource count for the root admin Memory usage
|
||||
# 3. Migrate vm, resource count should list properly.
|
||||
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].memorytotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["memory"])
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Resource count should match with the expected resource count")
|
||||
|
||||
host = find_suitable_host(self.apiclient, self.vm)
|
||||
self.debug("Migrating instance: %s to host: %s" % (self.vm.name, host.name))
|
||||
try:
|
||||
self.vm.migrate(self.apiclient, host.id)
|
||||
except Exception as e:
|
||||
self.fail("Failed to migrate instance: %s" % e)
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_migrate = account_list[0].memorytotal
|
||||
|
||||
self.assertEqual(resource_count, resource_count_after_migrate,
|
||||
"Resource count should be same after stopping the instance")
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_03_delete_instance(self):
|
||||
"""Test Deploy VM with 5 GB RAM & verify the usage"""
|
||||
|
||||
# Validate the following
|
||||
# 1. Create compute offering with 5 GB RAM & Deploy VM as root admin
|
||||
# 2. Update Resource count for the root admin Memory usage
|
||||
# 3. Delete instance, resource count should be 0 after delete operation.
|
||||
# 2. List Resource count for the root admin Memory usage
|
||||
# 3. Delete instance, resource count should be 0 after delete operation.
|
||||
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].memorytotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["memory"])
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Resource count should match with the expected resource count")
|
||||
|
||||
self.debug("Destroying instance: %s" % self.vm.name)
|
||||
try:
|
||||
|
|
@ -238,51 +293,87 @@ class TestMemoryLimits(cloudstackTestCase):
|
|||
except Exception as e:
|
||||
self.fail("Failed to delete instance: %s" % e)
|
||||
|
||||
# Wait for expunge interval to cleanup Memory
|
||||
wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"])
|
||||
# Wait for expunge interval to cleanup Memory
|
||||
wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"])
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
self.assertEqual(resource_count, 0 , "Resource count for %s should be 0" % get_resource_type(resource_id=9))#RAM
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_delete = account_list[0].memorytotal
|
||||
self.assertEqual(resource_count_after_delete, 0 , "Resource count for %s should be 0" % get_resource_type(resource_id=9))#RAM
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_04_deploy_multiple_vm_with_5gb_ram(self):
|
||||
"""Test Deploy multiple VM with 5 GB RAM & verify the usage"""
|
||||
|
||||
# Validate the following
|
||||
# 1. Create compute offering with 5 GB RAM
|
||||
# 2. Deploy multiple VMs with this service offering
|
||||
# 3. Update Resource count for the root admin Memory usage
|
||||
# 4. Memory usage should list properly
|
||||
# 3. List Resource count for the root admin Memory usage
|
||||
# 4. Memory usage should list properly
|
||||
|
||||
self.debug("Creating instances with service offering: %s" %
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].memorytotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["memory"])
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Resource count should match with the expected resource count")
|
||||
|
||||
self.debug("Creating two instances with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
vm_1 = self.createInstance(service_off=self.service_offering)
|
||||
self.createInstance(service_off=self.service_offering)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
self.createInstance(service_off=self.service_offering)
|
||||
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_new = account_list[0].memorytotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["memory"]) * 3 #Total 3 VMs
|
||||
|
||||
self.assertEqual(resource_count_new, expected_resource_count,
|
||||
"Resource count should match with the expected resource count")
|
||||
|
||||
self.debug("Destroying instance: %s" % vm_1.name)
|
||||
try:
|
||||
vm_1.delete(self.apiclient)
|
||||
except Exception as e:
|
||||
self.fail("Failed to delete instance: %s" % e)
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_delete = account_list[0].memorytotal
|
||||
|
||||
expected_resource_count -= int(self.services["service_offering"]["memory"])
|
||||
|
||||
self.assertEqual(resource_count_after_delete, expected_resource_count,
|
||||
"Resource count should match with the expected resource count")
|
||||
return
|
||||
|
||||
class TestMemoryUpdateResources(cloudstackTestCase):
|
||||
class TestDomainMemoryLimitsConfiguration(cloudstackTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.api_client = super(TestMemoryUpdateResources,
|
||||
cls.api_client = super(TestDomainMemoryLimitsConfiguration,
|
||||
cls).getClsTestClient().getApiClient()
|
||||
cls.services = Services().services
|
||||
# Get Zone, Domain and templates
|
||||
cls.domain = get_domain(cls.api_client, cls.services)
|
||||
cls.zone = get_zone(cls.api_client, cls.services)
|
||||
cls.services["mode"] = cls.zone.networktype
|
||||
cls.services["mode"] = cls.zone.networktype
|
||||
|
||||
cls.template = get_template(
|
||||
cls.api_client,
|
||||
|
|
@ -312,7 +403,7 @@ class TestMemoryUpdateResources(cloudstackTestCase):
|
|||
def setUp(self):
|
||||
self.apiclient = self.testClient.getApiClient()
|
||||
self.dbclient = self.testClient.getDbConnection()
|
||||
|
||||
|
||||
self.cleanup = []
|
||||
return
|
||||
|
||||
|
|
@ -329,8 +420,8 @@ class TestMemoryUpdateResources(cloudstackTestCase):
|
|||
self.debug("Deploying an instance in account: %s" %
|
||||
self.account.name)
|
||||
|
||||
if api_client is None:
|
||||
api_client = self.apiclient
|
||||
if api_client is None:
|
||||
api_client = self.apiclient
|
||||
|
||||
try:
|
||||
vm = VirtualMachine.create(
|
||||
|
|
@ -349,166 +440,153 @@ class TestMemoryUpdateResources(cloudstackTestCase):
|
|||
"Vm state should be running after deployment")
|
||||
return vm
|
||||
except Exception as e:
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
|
||||
def setupAccounts(self):
|
||||
|
||||
self.debug("Creating a domain under: %s" % self.domain.name)
|
||||
self.child_domain = Domain.create(self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.domain.id)
|
||||
self.child_do_admin = Account.create(
|
||||
self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True,
|
||||
domainid=self.child_domain.id
|
||||
)
|
||||
# Cleanup the resources created at end of test
|
||||
self.cleanup.append(self.child_do_admin)
|
||||
self.cleanup.append(self.child_domain)
|
||||
self.child_domain_1 = Domain.create(self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.domain.id)
|
||||
|
||||
self.debug("Updating the Memory resource count for domain: %s" %
|
||||
self.domain.name)
|
||||
Resources.updateLimit(self.apiclient,
|
||||
resourcetype=9,
|
||||
max=15360,
|
||||
account=self.child_do_admin.name,
|
||||
domainid=self.child_do_admin.domainid)
|
||||
self.child_do_admin_1 = Account.create(
|
||||
self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True,
|
||||
domainid=self.child_domain_1.id
|
||||
)
|
||||
# Cleanup the resources created at end of test
|
||||
self.cleanup.append(self.child_do_admin_1)
|
||||
self.cleanup.append(self.child_domain_1)
|
||||
|
||||
self.debug("Creating a domain under: %s" % self.domain.name)
|
||||
|
||||
self.domain = Domain.create(self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.domain.id)
|
||||
self.admin = Account.create(
|
||||
self.child_domain_2 = Domain.create(self.apiclient,
|
||||
services=self.services["domain"],
|
||||
parentdomainid=self.domain.id)
|
||||
|
||||
self.child_do_admin_2 = Account.create(
|
||||
self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True,
|
||||
domainid=self.domain.id)
|
||||
# Cleanup the resources created at end of test
|
||||
self.cleanup.append(self.admin)
|
||||
self.cleanup.append(self.domain)
|
||||
domainid=self.child_domain_2.id)
|
||||
# Cleanup the resources created at end of test
|
||||
self.cleanup.append(self.child_do_admin_2)
|
||||
self.cleanup.append(self.child_domain_2)
|
||||
|
||||
Resources.updateLimit(self.apiclient,
|
||||
resourcetype=9,
|
||||
max=15360,
|
||||
account=self.admin.name,
|
||||
domainid=self.admin.domainid)
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_01_change_service_offering(self):
|
||||
"""Test Deploy VM with 5 GB RAM & verify the usage"""
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_01_stop_start_instance(self):
|
||||
"""Test Deploy VM with 5 GB memory & verify the usage"""
|
||||
|
||||
# Validate the following
|
||||
# 1. Create compute offering with 5 GB RAM & Deploy VM as root admin
|
||||
# 2. Update Resource count for the root admin Memory usage
|
||||
# 3. Upgrade service offering, resource count should list properly.
|
||||
# 4. Downgrade service offering, resource count should list properly.
|
||||
# 1. Create compute offering with 5 GB memory in child domains of root domain & Deploy VM
|
||||
# 2. List Resource count memory usage
|
||||
# 3. Stop and Start instance, check resource count.
|
||||
# 4. Resource count should list properly.
|
||||
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts()
|
||||
users = {self.domain: self.admin,
|
||||
self.child_domain: self.child_do_admin
|
||||
users = {self.child_domain_1: self.child_do_admin_1,
|
||||
self.child_domain_2: self.child_do_admin_2
|
||||
}
|
||||
for domain, admin in users.items():
|
||||
self.account = admin
|
||||
self.domain = domain
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
|
||||
self.debug("Creating an instance with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
|
||||
vm = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].memorytotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["memory"])
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Initial resource count should match with the expected resource count")
|
||||
|
||||
self.debug("Stopping instance: %s" % vm.name)
|
||||
try:
|
||||
vm.stop(self.apiclient)
|
||||
except Exception as e:
|
||||
self.fail("Failed to stop instance: %s" % e)
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
|
||||
self.debug("Creating service offering with 7 GB RAM")
|
||||
self.services["service_offering"]["memory"] = 7168
|
||||
self.service_offering_7gb = ServiceOffering.create(
|
||||
self.apiclient,
|
||||
self.services["service_offering"])
|
||||
# Adding to cleanup list after execution
|
||||
self.cleanup.append(self.service_offering_7gb)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_stop = account_list[0].memorytotal
|
||||
|
||||
self.debug(
|
||||
"Upgrade service offering of instance %s from %s to %s" %
|
||||
(vm.name,
|
||||
self.service_offering.name,
|
||||
self.service_offering_7gb.name))
|
||||
|
||||
try:
|
||||
vm.change_service_offering(self.apiclient,
|
||||
serviceOfferingId=self.service_offering_7gb.id)
|
||||
except Exception as e:
|
||||
self.fail("Failed to change service offering of vm %s - %s" %
|
||||
(vm.name, e))
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
|
||||
self.debug(
|
||||
"Down grade service offering of instance %s from %s to %s" %
|
||||
(vm.name,
|
||||
self.service_offering_7gb.name,
|
||||
self.service_offering.name))
|
||||
|
||||
try:
|
||||
vm.change_service_offering(self.apiclient,
|
||||
serviceOfferingId=self.service_offering.id)
|
||||
except Exception as e:
|
||||
self.fail("Failed to change service offering of vm %s - %s" %
|
||||
(vm.name, e))
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
self.assertEqual(resource_count, resource_count_after_stop,
|
||||
"Resource count should be same after stopping the instance")
|
||||
|
||||
self.debug("Starting instance: %s" % vm.name)
|
||||
try:
|
||||
vm.start(self.apiclient)
|
||||
except Exception as e:
|
||||
self.fail("Failed to start instance: %s" % e)
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_start = account_list[0].memorytotal
|
||||
|
||||
self.assertEqual(resource_count_after_stop, resource_count_after_start,
|
||||
"Resource count should be same after starting the instance")
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_02_migrate_instance(self):
|
||||
"""Test Deploy VM with 5 GB RAM & verify the usage"""
|
||||
"""Test Deploy VM with 5 GB memory & verify the usage"""
|
||||
|
||||
# Validate the following
|
||||
# 1. Create compute offering with 5 GB RAM & Deploy VM as root admin
|
||||
# 2. Update Resource count for the root admin Memory usage
|
||||
# 3. Migrate vm, resource count should list properly.
|
||||
# 1. Create compute offering with 5 GB memory in child domains of root domain & Deploy VM
|
||||
# 2. List Resource count
|
||||
# 3. Migrate instance to another host
|
||||
# 4. Resource count should list properly.
|
||||
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts()
|
||||
users = {self.domain: self.admin,
|
||||
self.child_domain: self.child_do_admin
|
||||
users = {self.child_domain_1: self.child_do_admin_1,
|
||||
self.child_domain_2: self.child_do_admin_2
|
||||
}
|
||||
for domain, admin in users.items():
|
||||
self.account = admin
|
||||
self.domain = domain
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
|
||||
self.debug("Creating an instance with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
|
||||
vm = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].memorytotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["memory"])
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Initial resource count should with the expected resource count")
|
||||
|
||||
host = find_suitable_host(self.apiclient, vm)
|
||||
self.debug("Migrating instance: %s to host: %s" %
|
||||
(vm.name, host.name))
|
||||
|
|
@ -516,43 +594,56 @@ class TestMemoryUpdateResources(cloudstackTestCase):
|
|||
vm.migrate(self.apiclient, host.id)
|
||||
except Exception as e:
|
||||
self.fail("Failed to migrate instance: %s" % e)
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
|
||||
self.debug("Assigning VM to account: %s in domain: %s" %
|
||||
(self.admin.name,
|
||||
self.admin.domain))
|
||||
# TODO: Assign Virtual Machine function implementation
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_migrate = account_list[0].memorytotal
|
||||
|
||||
self.assertEqual(resource_count, resource_count_after_migrate,
|
||||
"Resource count should be same after starting the instance")
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_03_delete_instance(self):
|
||||
"""Test Deploy VM with 5 GB RAM & verify the usage"""
|
||||
|
||||
# Validate the following
|
||||
# 1. Create compute offering with 5 GB RAM & Deploy VM as root admin
|
||||
# 2. Update Resource count for the root admin Memory usage
|
||||
# 3. Delete instance, resource count should be 0 after delete operation.
|
||||
# 1. Create compute offering with 5 GB RAM in child domains of root domain & Deploy VM
|
||||
# 2. List Resource count for the Memory usage
|
||||
# 3. Delete instance
|
||||
# 4. Resource count should list as 0
|
||||
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts()
|
||||
users = {self.domain: self.admin,
|
||||
self.child_domain: self.child_do_admin
|
||||
users = {self.child_domain_1: self.child_do_admin_1,
|
||||
self.child_domain_2: self.child_do_admin_2
|
||||
}
|
||||
for domain, admin in users.items():
|
||||
self.account = admin
|
||||
self.domain = domain
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
|
||||
self.debug("Creating an instance with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
|
||||
vm = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].memorytotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["memory"])
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Initial resource count should match with the expected resource count")
|
||||
|
||||
self.debug("Destroying instance: %s" % vm.name)
|
||||
try:
|
||||
|
|
@ -560,56 +651,97 @@ class TestMemoryUpdateResources(cloudstackTestCase):
|
|||
except Exception as e:
|
||||
self.fail("Failed to delete instance: %s" % e)
|
||||
|
||||
# Wait for expunge interval to cleanup Memory
|
||||
wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"])
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].memorytotal
|
||||
self.assertEqual(resource_count, 0 , "Resource count for %s should be 0" % get_resource_type(resource_id=9))#RAM
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
def test_04_deploy_multiple_vm_with_5gb_ram(self):
|
||||
"""Test Deploy multiple VM with 5 GB RAM& verify the usage"""
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(configuration='max.account.memory')
|
||||
def test_04_deploy_multiple_vm(self):
|
||||
"""Test Deploy multiple VM with 5 GB memory & verify the usage"""
|
||||
#keep the configuration value - max.account.memory = 20480
|
||||
|
||||
# Validate the following
|
||||
# 1. Create compute offering with 5 GB RAM
|
||||
# 2. Deploy multiple VMs with this service offering
|
||||
# 3. Update Resource count for the root admin Memory usage
|
||||
# 4. Memory usage should list properly
|
||||
# 2. Deploy multiple VMs with this service offering in child domains of root domain
|
||||
# 3. List Resource count for the root admin Memory usage
|
||||
# 4. Memory usage should list properly
|
||||
|
||||
self.debug("Creating service offering with 5 GB RAM")
|
||||
self.service_offering = ServiceOffering.create(
|
||||
self.apiclient,
|
||||
self.services["service_offering"]
|
||||
)
|
||||
# Adding to cleanup list after execution
|
||||
self.cleanup.append(self.service_offering)
|
||||
|
||||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupAccounts()
|
||||
users = { self.domain: self.admin,
|
||||
self.child_domain: self.child_do_admin
|
||||
users = {self.child_domain_1: self.child_do_admin_1,
|
||||
self.child_domain_2: self.child_do_admin_2
|
||||
}
|
||||
for domain, admin in users.items():
|
||||
self.account = admin
|
||||
self.domain = domain
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
memory_account_gc = Resources.list(self.apiclient,
|
||||
resourcetype = 9, #Memory
|
||||
account = self.account.name,
|
||||
domainid = self.domain.id
|
||||
)
|
||||
|
||||
if memory_account_gc[0].max != 20480:
|
||||
self.skipTest("This test case requires configuration value max.account.memory to be 20480")
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.account.name,
|
||||
DomainName=self.account.domain)
|
||||
|
||||
self.debug("Creating an instance with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
vm_1 = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
vm_2 = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
vm_3 = self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
|
||||
self.debug("Deploying instance - Memory capacity is fully utilized")
|
||||
self.debug("Deploying instance - memory capacity is fully utilized")
|
||||
with self.assertRaises(Exception):
|
||||
self.createInstance(service_off=self.service_offering, api_client=api_client)
|
||||
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count = account_list[0].memorytotal
|
||||
|
||||
expected_resource_count = int(self.services["service_offering"]["memory"]) * 4 #Total 4 vms
|
||||
|
||||
self.assertEqual(resource_count, expected_resource_count,
|
||||
"Initial resource count should with the expected resource count")
|
||||
|
||||
self.debug("Destroying instance: %s" % vm_1.name)
|
||||
try:
|
||||
vm_1.delete(self.apiclient)
|
||||
except Exception as e:
|
||||
self.fail("Failed to delete instance: %s" % e)
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_delete = account_list[0].memorytotal
|
||||
|
||||
expected_resource_count -= int(self.services["service_offering"]["memory"])
|
||||
|
||||
self.assertEqual(resource_count_after_delete, expected_resource_count,
|
||||
"Resource count should match with the expected resource count")
|
||||
|
||||
host = find_suitable_host(self.apiclient, vm_2)
|
||||
self.debug("Migrating instance: %s to host: %s" % (vm_2.name,
|
||||
|
|
@ -618,9 +750,15 @@ class TestMemoryUpdateResources(cloudstackTestCase):
|
|||
vm_2.migrate(self.apiclient, host.id)
|
||||
except Exception as e:
|
||||
self.fail("Failed to migrate instance: %s" % e)
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.account, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
|
||||
vm_2.delete(self.apiclient)
|
||||
vm_3.delete(self.apiclient)
|
||||
return
|
||||
account_list = Account.list(self.apiclient, id=self.account.id)
|
||||
self.assertIsInstance(account_list,
|
||||
list,
|
||||
"List Accounts should return a valid response"
|
||||
)
|
||||
resource_count_after_migrate = account_list[0].memorytotal
|
||||
|
||||
self.debug(resource_count_after_migrate)
|
||||
self.assertEqual(resource_count_after_delete, resource_count_after_migrate,
|
||||
"Resource count should be same after migrating the instance")
|
||||
return
|
||||
|
|
|
|||
|
|
@ -30,8 +30,7 @@ from marvin.integration.lib.common import (get_domain,
|
|||
get_zone,
|
||||
get_template,
|
||||
cleanup_resources,
|
||||
wait_for_cleanup,
|
||||
get_updated_resource_count,
|
||||
wait_for_cleanup,
|
||||
find_suitable_host,
|
||||
get_resource_type
|
||||
)
|
||||
|
|
@ -97,7 +96,7 @@ class TestProjectsMemoryLimits(cloudstackTestCase):
|
|||
# Get Zone, Domain and templates
|
||||
cls.domain = get_domain(cls.api_client, cls.services)
|
||||
cls.zone = get_zone(cls.api_client, cls.services)
|
||||
cls.services["mode"] = cls.zone.networktype
|
||||
cls.services["mode"] = cls.zone.networktype
|
||||
|
||||
cls.template = get_template(
|
||||
cls.api_client,
|
||||
|
|
@ -127,7 +126,7 @@ class TestProjectsMemoryLimits(cloudstackTestCase):
|
|||
def setUp(self):
|
||||
self.apiclient = self.testClient.getApiClient()
|
||||
self.dbclient = self.testClient.getDbConnection()
|
||||
self.account = Account.create(
|
||||
self.account = Account.create(
|
||||
self.apiclient,
|
||||
self.services["account"],
|
||||
admin=True
|
||||
|
|
@ -137,14 +136,14 @@ class TestProjectsMemoryLimits(cloudstackTestCase):
|
|||
self.debug("Setting up account and domain hierarchy")
|
||||
self.setupProjectAccounts()
|
||||
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
api_client = self.testClient.createUserApiClient(
|
||||
UserName=self.admin.name,
|
||||
DomainName=self.admin.domain)
|
||||
|
||||
self.debug("Creating an instance with service offering: %s" %
|
||||
self.service_offering.name)
|
||||
self.vm = self.createInstance(project=self.project,
|
||||
service_off=self.service_offering, api_client=api_client)
|
||||
service_off=self.service_offering, api_client=api_client)
|
||||
return
|
||||
|
||||
def tearDown(self):
|
||||
|
|
@ -160,8 +159,8 @@ class TestProjectsMemoryLimits(cloudstackTestCase):
|
|||
self.debug("Deploying an instance in account: %s" %
|
||||
self.account.name)
|
||||
|
||||
if api_client is None:
|
||||
api_client = self.apiclient
|
||||
if api_client is None:
|
||||
api_client = self.apiclient
|
||||
|
||||
try:
|
||||
vm = VirtualMachine.create(
|
||||
|
|
@ -179,7 +178,7 @@ class TestProjectsMemoryLimits(cloudstackTestCase):
|
|||
"Vm state should be running after deployment")
|
||||
return vm
|
||||
except Exception as e:
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
self.fail("Failed to deploy an instance: %s" % e)
|
||||
|
||||
def setupProjectAccounts(self):
|
||||
|
||||
|
|
@ -217,24 +216,27 @@ class TestProjectsMemoryLimits(cloudstackTestCase):
|
|||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(configuration='max.projects.memory')
|
||||
def test_01_project_vmlifecycle_reboot_instance(self):
|
||||
"""Test max.projects.memory global configuration"""
|
||||
def test_01_project_vmlifecycle_start_stop_instance(self):
|
||||
|
||||
# Validate the following
|
||||
# 1. Set (max.project.memory=10) as the max limit to
|
||||
# Domain1 (max.account.memory=10)
|
||||
# 2. Assign account to projects and verify the resource updates
|
||||
# 3. Deploy VM with the accounts added to the project
|
||||
# 4. Stop VM of an accounts added to the project to a new host
|
||||
# 5. Resource count should list properly
|
||||
# 6. Start VM of an accounts added to the project to a new host
|
||||
# 7. Resource count should list properly
|
||||
# 1. Assign account to projects and verify the resource updates
|
||||
# 2. Deploy VM with the accounts added to the project
|
||||
# 3. Stop VM of an accounts added to the project to a new host
|
||||
# 4. Resource count should list properly
|
||||
# 5. Start VM of an accounts added to the project to a new host
|
||||
# 6. Resource count should list properly
|
||||
|
||||
self.debug("Checking memory resource count for project: %s" % self.project.name)
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.admin, project=self.project, rtype=9)#RAM
|
||||
project_list = Project.list(self.apiclient, id=self.project.id, listall=True)
|
||||
self.debug(project_list)
|
||||
self.assertIsInstance(project_list,
|
||||
list,
|
||||
"List Projects should return a valid response"
|
||||
)
|
||||
resource_count = project_list[0].memorytotal
|
||||
|
||||
self.debug(resource_count)
|
||||
|
||||
|
||||
self.debug("Stopping instance: %s" % self.vm.name)
|
||||
try:
|
||||
self.vm.stop(self.apiclient)
|
||||
|
|
@ -242,8 +244,15 @@ class TestProjectsMemoryLimits(cloudstackTestCase):
|
|||
self.fail("Failed to stop instance: %s" % e)
|
||||
|
||||
self.debug("Checking memory resource count for project: %s" % self.project.name)
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.admin, project=self.project, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
project_list = Project.list(self.apiclient, id=self.project.id, listall=True)
|
||||
self.assertIsInstance(project_list,
|
||||
list,
|
||||
"List Projects should return a valid response"
|
||||
)
|
||||
resource_count_after_stop = project_list[0].memorytotal
|
||||
|
||||
self.assertEqual(resource_count, resource_count_after_stop,
|
||||
"Resource count should be same after stopping the instance")
|
||||
|
||||
self.debug("Starting instance: %s" % self.vm.name)
|
||||
try:
|
||||
|
|
@ -252,26 +261,35 @@ class TestProjectsMemoryLimits(cloudstackTestCase):
|
|||
self.fail("Failed to start instance: %s" % e)
|
||||
|
||||
self.debug("Checking memory resource count for project: %s" % self.project.name)
|
||||
get_updated_resource_count(self.apiclient, account=self.admin, project=self.project, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
project_list = Project.list(self.apiclient, id=self.project.id, listall=True)
|
||||
self.assertIsInstance(project_list,
|
||||
list,
|
||||
"List Projects should return a valid response"
|
||||
)
|
||||
resource_count_after_start = project_list[0].memorytotal
|
||||
|
||||
self.assertEqual(resource_count, resource_count_after_start,
|
||||
"Resource count should be same after starting the instance")
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(configuration='max.projects.memory')
|
||||
def test_02_project_vmlifecycle_migrate_instance(self):
|
||||
"""Test max.projects.memory global configuration"""
|
||||
|
||||
# Validate the following
|
||||
# 1. Set (max.project.memory=10) as the max limit to
|
||||
# Domain1 (max.account.memory=10)
|
||||
# 2. Assign account to projects and verify the resource updates
|
||||
# 3. Deploy VM with the accounts added to the project
|
||||
# 4. Migrate VM of an accounts added to the project to a new host
|
||||
# 5. Resource count should list properly.
|
||||
# 1. Assign account to projects and verify the resource updates
|
||||
# 2. Deploy VM with the accounts added to the project
|
||||
# 3. Migrate VM of an accounts added to the project to a new host
|
||||
# 4. Resource count should list properly.
|
||||
|
||||
self.debug("Checking memory resource count for project: %s" % self.project.name)
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.admin, project=self.project, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
project_list = Project.list(self.apiclient, id=self.project.id, listall=True)
|
||||
self.debug(project_list)
|
||||
self.assertIsInstance(project_list,
|
||||
list,
|
||||
"List Projects should return a valid response"
|
||||
)
|
||||
resource_count = project_list[0].memorytotal
|
||||
self.debug(resource_count)
|
||||
|
||||
host = find_suitable_host(self.apiclient, self.vm)
|
||||
self.debug("Migrating instance: %s to host: %s" %
|
||||
|
|
@ -280,28 +298,37 @@ class TestProjectsMemoryLimits(cloudstackTestCase):
|
|||
self.vm.migrate(self.apiclient, host.id)
|
||||
except Exception as e:
|
||||
self.fail("Failed to migrate instance: %s" % e)
|
||||
|
||||
|
||||
self.debug("Checking memory resource count for project: %s" % self.project.name)
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.admin, project=self.project, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
project_list = Project.list(self.apiclient, id=self.project.id, listall=True)
|
||||
self.assertIsInstance(project_list,
|
||||
list,
|
||||
"List Projects should return a valid response"
|
||||
)
|
||||
resource_count_after_migrate = project_list[0].memorytotal
|
||||
|
||||
self.assertEqual(resource_count, resource_count_after_migrate,
|
||||
"Resource count should be same after migrating the instance")
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "advancedns","simulator"])
|
||||
@attr(configuration='max.projects.memory')
|
||||
def test_03_project_vmlifecycle_delete_instance(self):
|
||||
"""Test max.projects.memory global configuration"""
|
||||
|
||||
# Validate the following
|
||||
# 1. Set (max.project.memory=10) as the max limit to
|
||||
# Domain1 (max.account.memory=10)
|
||||
# 2. Assign account to projects and verify the resource updates
|
||||
# 3. Deploy VM with the accounts added to the project
|
||||
# 4. Destroy VM of an accounts added to the project
|
||||
# 5. Resource count should list as 0 after destroying the instance
|
||||
# 1. Assign account to projects and verify the resource updates
|
||||
# 2. Deploy VM with the accounts added to the project
|
||||
# 3. Destroy VM of an accounts added to the project
|
||||
# 4. Resource count should list as 0 after destroying the instance
|
||||
|
||||
self.debug("Checking memory resource count for project: %s" % self.project.name)
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.admin, project=self.project, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
project_list = Project.list(self.apiclient, id=self.project.id, listall=True)
|
||||
self.debug(project_list)
|
||||
self.assertIsInstance(project_list,
|
||||
list,
|
||||
"List Projects should return a valid response"
|
||||
)
|
||||
resource_count = project_list[0].memorytotal
|
||||
self.debug(resource_count)
|
||||
|
||||
self.debug("Destroying instance: %s" % self.vm.name)
|
||||
try:
|
||||
|
|
@ -309,13 +336,15 @@ class TestProjectsMemoryLimits(cloudstackTestCase):
|
|||
except Exception as e:
|
||||
self.fail("Failed to delete instance: %s" % e)
|
||||
|
||||
# Wait for expunge interval to cleanup Memory
|
||||
wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"])
|
||||
# Wait for expunge interval to cleanup Memory
|
||||
wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"])
|
||||
|
||||
self.debug("Checking memory resource count for project: %s" % self.project.name)
|
||||
resource_count = get_updated_resource_count(self.apiclient, account=self.admin, project=self.project, rtype=9)#RAM
|
||||
self.debug(resource_count)
|
||||
self.assertEqual(resource_count, 0 , "Resource count for %s should be 0" % get_resource_type(resource_id=9))#RAM
|
||||
project_list = Project.list(self.apiclient, id=self.project.id, listall=True)
|
||||
self.assertIsInstance(project_list,
|
||||
list,
|
||||
"List Projects should return a valid response"
|
||||
)
|
||||
resource_count_after_delete = project_list[0].memorytotal
|
||||
self.assertEqual(resource_count_after_delete, 0 , "Resource count for %s should be 0" % get_resource_type(resource_id=9))#RAM
|
||||
return
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required byswa applicable law or agreed to in writing,
|
||||
# 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
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
"""
|
||||
"""
|
||||
#Import Local Modules
|
||||
#import unittest
|
||||
import unittest
|
||||
from nose.plugins.attrib import attr
|
||||
from marvin.cloudstackTestCase import cloudstackTestCase
|
||||
from marvin.integration.lib.base import (Account,
|
||||
|
|
@ -198,7 +198,6 @@ class TestEgressFWRules(cloudstackTestCase):
|
|||
# Enable Network offering
|
||||
self.network_offering.update(self.apiclient, state='Enabled')
|
||||
|
||||
|
||||
def create_vm(self, pfrule=False, egress_policy=True, RR=False):
|
||||
self.create_network_offering(egress_policy, RR)
|
||||
# Creating network using the network offering created
|
||||
|
|
@ -229,20 +228,7 @@ class TestEgressFWRules(cloudstackTestCase):
|
|||
|
||||
def exec_script_on_user_vm(self, script, exec_cmd_params, expected_result, negative_test=False):
|
||||
try:
|
||||
if self.apiclient.hypervisor.lower() == 'vmware':
|
||||
#SSH is done via management server for Vmware
|
||||
sourceip = self.apiclient.connection.mgtSvr
|
||||
else:
|
||||
#For others, we will have to get the ipaddress of host connected to vm
|
||||
hosts = list_hosts(self.apiclient,
|
||||
id=self.virtual_machine.hostid)
|
||||
self.assertEqual(isinstance(hosts, list),
|
||||
True,
|
||||
"Check list response returns a valid list")
|
||||
host = hosts[0]
|
||||
sourceip = host.ipaddress
|
||||
#Once host or mgt server is reached, SSH to the router connected to VM
|
||||
# look for Router for Cloudstack VM network.
|
||||
|
||||
vm_network_id = self.virtual_machine.nic[0].networkid
|
||||
vm_ipaddress = self.virtual_machine.nic[0].ipaddress
|
||||
list_routers_response = list_routers(self.apiclient,
|
||||
|
|
@ -253,6 +239,26 @@ class TestEgressFWRules(cloudstackTestCase):
|
|||
True,
|
||||
"Check for list routers response return valid data")
|
||||
router = list_routers_response[0]
|
||||
|
||||
#Once host or mgt server is reached, SSH to the router connected to VM
|
||||
# look for Router for Cloudstack VM network.
|
||||
if self.apiclient.hypervisor.lower() == 'vmware':
|
||||
#SSH is done via management server for Vmware
|
||||
sourceip = self.apiclient.connection.mgtSvr
|
||||
else:
|
||||
#For others, we will have to get the ipaddress of host connected to vm
|
||||
hosts = list_hosts(self.apiclient,
|
||||
id=router.hostid)
|
||||
self.assertEqual(isinstance(hosts, list),
|
||||
True,
|
||||
"Check list response returns a valid list")
|
||||
host = hosts[0]
|
||||
sourceip = host.ipaddress
|
||||
|
||||
self.debug("Sleep %s seconds for network on router to be up"
|
||||
% self.services['sleep'])
|
||||
time.sleep(self.services['sleep'])
|
||||
|
||||
if self.apiclient.hypervisor.lower() == 'vmware':
|
||||
key_file = " -i /var/cloudstack/management/.ssh/id_rsa "
|
||||
else:
|
||||
|
|
@ -266,7 +272,6 @@ class TestEgressFWRules(cloudstackTestCase):
|
|||
"expect \"root@%s's password: \"\n" % (vm_ipaddress) + \
|
||||
"send \"password\r\"\n" + \
|
||||
"interact\n"
|
||||
|
||||
self.debug("expect_script>>\n%s<<expect_script" % expect_script)
|
||||
|
||||
script_file = '/tmp/expect_script.exp'
|
||||
|
|
@ -392,7 +397,6 @@ class TestEgressFWRules(cloudstackTestCase):
|
|||
"['0']",
|
||||
negative_test=False)
|
||||
|
||||
|
||||
@attr(tags = ["advanced"])
|
||||
@log_test_exceptions
|
||||
def test_01_1_egress_fr1(self):
|
||||
|
|
|
|||