mirror of
https://github.com/apache/cloudstack.git
synced 2025-12-16 18:43:26 +01:00
Merge branch 'master' of ssh://git.cloud.com/var/lib/git/cloudstack-oss
This commit is contained in:
commit
6d101d554e
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
|
|
||||||
#Labels
|
#Labels
|
||||||
|
label.action.edit.host=Edit Host
|
||||||
|
|
||||||
network.rate=Network Rate
|
network.rate=Network Rate
|
||||||
|
|
||||||
ICMP.type=ICMP Type
|
ICMP.type=ICMP Type
|
||||||
|
|||||||
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
|
|
||||||
#Labels
|
#Labels
|
||||||
|
label.action.edit.host=edición Anfitrión
|
||||||
|
|
||||||
network.rate=Tasa de red
|
network.rate=Tasa de red
|
||||||
|
|
||||||
ICMP.type=Tipo ICMP
|
ICMP.type=Tipo ICMP
|
||||||
|
|||||||
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
|
|
||||||
#Labels
|
#Labels
|
||||||
|
label.action.edit.host=ホストを編集する
|
||||||
|
|
||||||
network.rate=ネットワーク速度
|
network.rate=ネットワーク速度
|
||||||
|
|
||||||
ICMP.type=ICMPタイプ
|
ICMP.type=ICMPタイプ
|
||||||
|
|||||||
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
|
|
||||||
#Labels
|
#Labels
|
||||||
|
label.action.edit.host=编辑主机
|
||||||
|
|
||||||
network.rate=网络速率
|
network.rate=网络速率
|
||||||
|
|
||||||
ICMP.type=ICMP类型
|
ICMP.type=ICMP类型
|
||||||
|
|||||||
@ -601,7 +601,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
String[] addRules = rules[LoadBalancerConfigurator.ADD];
|
String[] addRules = rules[LoadBalancerConfigurator.ADD];
|
||||||
String[] removeRules = rules[LoadBalancerConfigurator.REMOVE];
|
String[] removeRules = rules[LoadBalancerConfigurator.REMOVE];
|
||||||
|
String[] statRules = rules[LoadBalancerConfigurator.STATS];
|
||||||
|
|
||||||
String args = "";
|
String args = "";
|
||||||
args += "-i " + routerIp;
|
args += "-i " + routerIp;
|
||||||
@ -624,7 +625,16 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||||||
|
|
||||||
args += " -d " + sb.toString();
|
args += " -d " + sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sb = new StringBuilder();
|
||||||
|
if (statRules.length > 0) {
|
||||||
|
for (int i = 0; i < statRules.length; i++) {
|
||||||
|
sb.append(statRules[i]).append(',');
|
||||||
|
}
|
||||||
|
|
||||||
|
args += " -s " + sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
Pair<Boolean, String> result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null, "scp " + tmpCfgFilePath + " /etc/haproxy/haproxy.cfg.new");
|
Pair<Boolean, String> result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null, "scp " + tmpCfgFilePath + " /etc/haproxy/haproxy.cfg.new");
|
||||||
|
|
||||||
if (!result.first()) {
|
if (!result.first()) {
|
||||||
@ -1077,6 +1087,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||||||
if (getVmState(vmMo) != State.Stopped)
|
if (getVmState(vmMo) != State.Stopped)
|
||||||
vmMo.safePowerOff(_shutdown_waitMs);
|
vmMo.safePowerOff(_shutdown_waitMs);
|
||||||
vmMo.tearDownDevices(new Class<?>[] { VirtualDisk.class, VirtualEthernetCard.class });
|
vmMo.tearDownDevices(new Class<?>[] { VirtualDisk.class, VirtualEthernetCard.class });
|
||||||
|
vmMo.ensureScsiDeviceController();
|
||||||
} else {
|
} else {
|
||||||
ManagedObjectReference morDc = hyperHost.getHyperHostDatacenter();
|
ManagedObjectReference morDc = hyperHost.getHyperHostDatacenter();
|
||||||
assert (morDc != null);
|
assert (morDc != null);
|
||||||
@ -1091,7 +1102,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||||||
|
|
||||||
if (getVmState(vmMo) != State.Stopped)
|
if (getVmState(vmMo) != State.Stopped)
|
||||||
vmMo.safePowerOff(_shutdown_waitMs);
|
vmMo.safePowerOff(_shutdown_waitMs);
|
||||||
vmMo.tearDownDevices(new Class<?>[] { VirtualDisk.class, VirtualEthernetCard.class });
|
vmMo.tearDownDevices(new Class<?>[] { VirtualDisk.class, VirtualEthernetCard.class });
|
||||||
|
vmMo.ensureScsiDeviceController();
|
||||||
} else {
|
} else {
|
||||||
int ramMb = (int) (vmSpec.getMinRam() / (1024 * 1024));
|
int ramMb = (int) (vmSpec.getMinRam() / (1024 * 1024));
|
||||||
Pair<ManagedObjectReference, DatastoreMO> rootDiskDataStoreDetails = null;
|
Pair<ManagedObjectReference, DatastoreMO> rootDiskDataStoreDetails = null;
|
||||||
|
|||||||
@ -206,7 +206,7 @@ public class HAProxyConfigurator implements LoadBalancerConfigurator {
|
|||||||
result.addAll(Arrays.asList(defaultsSection));
|
result.addAll(Arrays.asList(defaultsSection));
|
||||||
if (!lbCmd.lbStatsVisibility.equals("disabled"))
|
if (!lbCmd.lbStatsVisibility.equals("disabled"))
|
||||||
{
|
{
|
||||||
if (lbCmd.lbStatsVisibility.equals("guest-network"))
|
if (lbCmd.lbStatsVisibility.equals("guest-network") || lbCmd.lbStatsVisibility.equals("link-local"))
|
||||||
{
|
{
|
||||||
result.add(getBlankLine());
|
result.add(getBlankLine());
|
||||||
|
|
||||||
|
|||||||
10
deps/.classpath
vendored
10
deps/.classpath
vendored
@ -6,16 +6,11 @@
|
|||||||
<classpathentry exported="true" kind="lib" path="cloud-backport-util-concurrent-3.0.jar"/>
|
<classpathentry exported="true" kind="lib" path="cloud-backport-util-concurrent-3.0.jar"/>
|
||||||
<classpathentry exported="true" kind="lib" path="cloud-bcprov-jdk16-1.45.jar"/>
|
<classpathentry exported="true" kind="lib" path="cloud-bcprov-jdk16-1.45.jar"/>
|
||||||
<classpathentry exported="true" kind="lib" path="cloud-cglib.jar"/>
|
<classpathentry exported="true" kind="lib" path="cloud-cglib.jar"/>
|
||||||
<classpathentry exported="true" kind="lib" path="cloud-commons-codec-1.4.jar"/>
|
|
||||||
<classpathentry exported="true" kind="lib" path="cloud-commons-collections-3.2.1.jar"/>
|
<classpathentry exported="true" kind="lib" path="cloud-commons-collections-3.2.1.jar"/>
|
||||||
<classpathentry exported="true" kind="lib" path="cloud-commons-dbcp-1.2.2.jar"/>
|
|
||||||
<classpathentry exported="true" kind="lib" path="cloud-commons-discovery.jar"/>
|
<classpathentry exported="true" kind="lib" path="cloud-commons-discovery.jar"/>
|
||||||
<classpathentry exported="true" kind="lib" path="cloud-commons-httpclient-3.1.jar"/>
|
|
||||||
<classpathentry exported="true" kind="lib" path="cloud-commons-logging-1.1.1.jar"/>
|
<classpathentry exported="true" kind="lib" path="cloud-commons-logging-1.1.1.jar"/>
|
||||||
<classpathentry exported="true" kind="lib" path="cloud-commons-pool-1.4.jar"/>
|
|
||||||
<classpathentry exported="true" kind="lib" path="cloud-ehcache.jar"/>
|
<classpathentry exported="true" kind="lib" path="cloud-ehcache.jar"/>
|
||||||
<classpathentry exported="true" kind="lib" path="cloud-email.jar"/>
|
<classpathentry exported="true" kind="lib" path="cloud-email.jar"/>
|
||||||
<classpathentry exported="true" kind="lib" path="cloud-gson.jar"/>
|
|
||||||
<classpathentry exported="true" kind="lib" path="cloud-httpcore-4.0.jar"/>
|
<classpathentry exported="true" kind="lib" path="cloud-httpcore-4.0.jar"/>
|
||||||
<classpathentry exported="true" kind="lib" path="cloud-jsch-0.1.42.jar"/>
|
<classpathentry exported="true" kind="lib" path="cloud-jsch-0.1.42.jar"/>
|
||||||
<classpathentry exported="true" kind="lib" path="cloud-jstl-1.2.jar"/>
|
<classpathentry exported="true" kind="lib" path="cloud-jstl-1.2.jar"/>
|
||||||
@ -55,5 +50,10 @@
|
|||||||
<classpathentry exported="true" kind="lib" path="cloud-junit.jar"/>
|
<classpathentry exported="true" kind="lib" path="cloud-junit.jar"/>
|
||||||
<classpathentry exported="true" kind="lib" path="cloud-selenium-java-client-driver.jar"/>
|
<classpathentry exported="true" kind="lib" path="cloud-selenium-java-client-driver.jar"/>
|
||||||
<classpathentry exported="true" kind="lib" path="cloud-selenium-server.jar"/>
|
<classpathentry exported="true" kind="lib" path="cloud-selenium-server.jar"/>
|
||||||
|
<classpathentry exported="true" kind="lib" path="cloud-commons-codec-1.5.jar"/>
|
||||||
|
<classpathentry exported="true" kind="lib" path="cloud-commons-dbcp-1.4.jar"/>
|
||||||
|
<classpathentry exported="true" kind="lib" path="cloud-commons-pool-1.5.6.jar"/>
|
||||||
|
<classpathentry exported="true" kind="lib" path="cloud-google-gson-1.7.1.jar"/>
|
||||||
|
<classpathentry exported="true" kind="lib" path="cloud-httpclient-4.1.2.jar"/>
|
||||||
<classpathentry kind="output" path="bin"/>
|
<classpathentry kind="output" path="bin"/>
|
||||||
</classpath>
|
</classpath>
|
||||||
|
|||||||
BIN
deps/cloud-commons-codec-1.4.jar
vendored
BIN
deps/cloud-commons-codec-1.4.jar
vendored
Binary file not shown.
BIN
deps/cloud-commons-codec-1.5.jar
vendored
Normal file
BIN
deps/cloud-commons-codec-1.5.jar
vendored
Normal file
Binary file not shown.
BIN
deps/cloud-commons-dbcp-1.2.2.jar
vendored
BIN
deps/cloud-commons-dbcp-1.2.2.jar
vendored
Binary file not shown.
BIN
deps/cloud-commons-dbcp-1.4.jar
vendored
Normal file
BIN
deps/cloud-commons-dbcp-1.4.jar
vendored
Normal file
Binary file not shown.
BIN
deps/cloud-commons-httpclient-3.1.jar
vendored
BIN
deps/cloud-commons-httpclient-3.1.jar
vendored
Binary file not shown.
BIN
deps/cloud-commons-pool-1.4.jar
vendored
BIN
deps/cloud-commons-pool-1.4.jar
vendored
Binary file not shown.
BIN
deps/cloud-commons-pool-1.5.6.jar
vendored
Normal file
BIN
deps/cloud-commons-pool-1.5.6.jar
vendored
Normal file
Binary file not shown.
BIN
deps/cloud-google-gson-1.7.1.jar
vendored
Normal file
BIN
deps/cloud-google-gson-1.7.1.jar
vendored
Normal file
Binary file not shown.
BIN
deps/cloud-gson.jar
vendored
BIN
deps/cloud-gson.jar
vendored
Binary file not shown.
BIN
deps/cloud-httpclient-4.1.2.jar
vendored
Normal file
BIN
deps/cloud-httpclient-4.1.2.jar
vendored
Normal file
Binary file not shown.
44
patches/systemvm/debian/config/root/func.sh
Normal file
44
patches/systemvm/debian/config/root/func.sh
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# getLockFile() parameters
|
||||||
|
# $1 lock filename
|
||||||
|
# $2 timeout seconds
|
||||||
|
getLockFile() {
|
||||||
|
__locked=0
|
||||||
|
__LOCKFILE="/tmp/$1.lock"
|
||||||
|
if [ $2 ]
|
||||||
|
then
|
||||||
|
__TIMEOUT=$2
|
||||||
|
else
|
||||||
|
__TIMEOUT=10
|
||||||
|
fi
|
||||||
|
|
||||||
|
for i in `seq 1 $__TIMEOUT`
|
||||||
|
do
|
||||||
|
if [ ! -e $__LOCKFILE ]
|
||||||
|
then
|
||||||
|
touch $__LOCKFILE
|
||||||
|
__locked=1
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
logger -t cloud "sleep 1 second wait for the lock file " $__LOCKFILE
|
||||||
|
done
|
||||||
|
if [ $__locked -ne 1 ]
|
||||||
|
then
|
||||||
|
logger -t cloud "fail to acquire the lock file $__LOCKFILE after $__TIMEOUT seconds time out!"
|
||||||
|
fi
|
||||||
|
echo $__locked
|
||||||
|
}
|
||||||
|
|
||||||
|
# releaseLockFile() parameters
|
||||||
|
# $1 lock filename
|
||||||
|
# $2 locked(1) or not(0)
|
||||||
|
releaseLockFile() {
|
||||||
|
__LOCKFILE="/tmp/$1.lock"
|
||||||
|
__locked=$2
|
||||||
|
if [ "$__locked" == "1" ]
|
||||||
|
then
|
||||||
|
rm $__LOCKFILE
|
||||||
|
fi
|
||||||
|
}
|
||||||
@ -79,7 +79,7 @@ fw_remove_backup() {
|
|||||||
sudo iptables -X back_load_balancer_$vif 2> /dev/null
|
sudo iptables -X back_load_balancer_$vif 2> /dev/null
|
||||||
done
|
done
|
||||||
sudo iptables -F back_lb_stats 2> /dev/null
|
sudo iptables -F back_lb_stats 2> /dev/null
|
||||||
sudo iptables -D INPUT -i $STAT_IF -p tcp -j back_lb_stats 2> /dev/null
|
sudo iptables -D INPUT -p tcp -j back_lb_stats 2> /dev/null
|
||||||
sudo iptables -X back_lb_stats 2> /dev/null
|
sudo iptables -X back_lb_stats 2> /dev/null
|
||||||
}
|
}
|
||||||
fw_restore() {
|
fw_restore() {
|
||||||
@ -90,7 +90,7 @@ fw_restore() {
|
|||||||
sudo iptables -E back_load_balancer_$vif load_balancer_$vif 2> /dev/null
|
sudo iptables -E back_load_balancer_$vif load_balancer_$vif 2> /dev/null
|
||||||
done
|
done
|
||||||
sudo iptables -F lb_stats 2> /dev/null
|
sudo iptables -F lb_stats 2> /dev/null
|
||||||
sudo iptables -D INPUT -i $STAT_IF -p tcp -j lb_stats 2> /dev/null
|
sudo iptables -D INPUT -p tcp -j lb_stats 2> /dev/null
|
||||||
sudo iptables -X lb_stats 2> /dev/null
|
sudo iptables -X lb_stats 2> /dev/null
|
||||||
sudo iptables -E back_lb_stats lb_stats 2> /dev/null
|
sudo iptables -E back_lb_stats lb_stats 2> /dev/null
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ fw_entry() {
|
|||||||
done
|
done
|
||||||
sudo iptables -E lb_stats back_lb_stats 2> /dev/null
|
sudo iptables -E lb_stats back_lb_stats 2> /dev/null
|
||||||
sudo iptables -N lb_stats 2> /dev/null
|
sudo iptables -N lb_stats 2> /dev/null
|
||||||
sudo iptables -A INPUT -i $STAT_IF -p tcp -j lb_stats
|
sudo iptables -A INPUT -p tcp -j lb_stats
|
||||||
|
|
||||||
for i in $a
|
for i in $a
|
||||||
do
|
do
|
||||||
@ -259,8 +259,6 @@ if [ "$VIF_LIST" == "eth0" ]
|
|||||||
then
|
then
|
||||||
ip_entry $addedIps $removedIps
|
ip_entry $addedIps $removedIps
|
||||||
fi
|
fi
|
||||||
# FIXME make the load balancer stat interface generic
|
|
||||||
STAT_IF="eth0"
|
|
||||||
|
|
||||||
# hot reconfigure haproxy
|
# hot reconfigure haproxy
|
||||||
reconfig_lb $cfgfile
|
reconfig_lb $cfgfile
|
||||||
|
|||||||
@ -18,9 +18,18 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
|
name="reconfigLB"
|
||||||
|
|
||||||
|
source func.sh
|
||||||
|
locked=$(getLockFile $name)
|
||||||
|
if [ "$locked" != "1" ]
|
||||||
|
then
|
||||||
|
logger -t cloud "Fail to get the lock for " $name
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ret=0
|
||||||
# save previous state
|
# save previous state
|
||||||
mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.old
|
mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.old
|
||||||
mv /var/run/haproxy.pid /var/run/haproxy.pid.old
|
mv /var/run/haproxy.pid /var/run/haproxy.pid.old
|
||||||
@ -32,7 +41,7 @@
|
|||||||
echo "New haproxy instance successfully loaded, stopping previous one."
|
echo "New haproxy instance successfully loaded, stopping previous one."
|
||||||
kill -KILL $(cat /var/run/haproxy.pid.old)
|
kill -KILL $(cat /var/run/haproxy.pid.old)
|
||||||
rm -f /var/run/haproxy.pid.old
|
rm -f /var/run/haproxy.pid.old
|
||||||
exit 0
|
ret=0
|
||||||
else
|
else
|
||||||
echo "New instance failed to start, resuming previous one."
|
echo "New instance failed to start, resuming previous one."
|
||||||
kill -TTIN $(cat /var/run/haproxy.pid.old)
|
kill -TTIN $(cat /var/run/haproxy.pid.old)
|
||||||
@ -40,5 +49,9 @@
|
|||||||
mv /var/run/haproxy.pid.old /var/run/haproxy.pid
|
mv /var/run/haproxy.pid.old /var/run/haproxy.pid
|
||||||
mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.new
|
mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.new
|
||||||
mv /etc/haproxy/haproxy.cfg.old /etc/haproxy/haproxy.cfg
|
mv /etc/haproxy/haproxy.cfg.old /etc/haproxy/haproxy.cfg
|
||||||
exit 1
|
ret=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
releaseLockFile $name $locked
|
||||||
|
|
||||||
|
exit $ret
|
||||||
|
|||||||
@ -264,7 +264,7 @@ public class AlertManagerImpl implements AlertManager {
|
|||||||
try {
|
try {
|
||||||
txn.start();
|
txn.start();
|
||||||
// Calculate new Public IP capacity
|
// Calculate new Public IP capacity
|
||||||
List<DataCenterVO> datacenters = _dcDao.listAllIncludingRemoved();
|
List<DataCenterVO> datacenters = _dcDao.listAll();
|
||||||
for (DataCenterVO datacenter : datacenters) {
|
for (DataCenterVO datacenter : datacenters) {
|
||||||
long dcId = datacenter.getId();
|
long dcId = datacenter.getId();
|
||||||
|
|
||||||
@ -283,7 +283,7 @@ public class AlertManagerImpl implements AlertManager {
|
|||||||
|
|
||||||
txn.start();
|
txn.start();
|
||||||
// Calculate new Private IP capacity
|
// Calculate new Private IP capacity
|
||||||
List<HostPodVO> pods = _podDao.listAllIncludingRemoved();
|
List<HostPodVO> pods = _podDao.listAll();
|
||||||
for (HostPodVO pod : pods) {
|
for (HostPodVO pod : pods) {
|
||||||
long podId = pod.getId();
|
long podId = pod.getId();
|
||||||
long dcId = pod.getDataCenterId();
|
long dcId = pod.getDataCenterId();
|
||||||
|
|||||||
@ -58,7 +58,7 @@ public enum Config {
|
|||||||
StorageTemplateCleanupEnabled("Storage", ManagementServer.class, Boolean.class, "storage.template.cleanup.enabled", "true", "Enable/disable template cleanup activity, only take effect when overall storage cleanup is enabled", null),
|
StorageTemplateCleanupEnabled("Storage", ManagementServer.class, Boolean.class, "storage.template.cleanup.enabled", "true", "Enable/disable template cleanup activity, only take effect when overall storage cleanup is enabled", null),
|
||||||
|
|
||||||
// Network
|
// Network
|
||||||
NetworkLBHaproxyStatsVisbility("Network", ManagementServer.class, String.class, "network.loadbalancer.haproxy.stats.visibility", "global", "Load Balancer(haproxy) stats visibilty, it can be global,guest-network,disabled", null),
|
NetworkLBHaproxyStatsVisbility("Network", ManagementServer.class, String.class, "network.loadbalancer.haproxy.stats.visibility", "global", "Load Balancer(haproxy) stats visibilty, it can take the following four parameters : global,guest-network,link-local,disabled", null),
|
||||||
NetworkLBHaproxyStatsUri("Network", ManagementServer.class, String.class, "network.loadbalancer.haproxy.stats.uri","/admin?stats","Load Balancer(haproxy) uri.",null),
|
NetworkLBHaproxyStatsUri("Network", ManagementServer.class, String.class, "network.loadbalancer.haproxy.stats.uri","/admin?stats","Load Balancer(haproxy) uri.",null),
|
||||||
NetworkLBHaproxyStatsAuth("Network", ManagementServer.class, String.class, "network.loadbalancer.haproxy.stats.auth","admin1:AdMiN123","Load Balancer(haproxy) authetication string in the format username:password",null),
|
NetworkLBHaproxyStatsAuth("Network", ManagementServer.class, String.class, "network.loadbalancer.haproxy.stats.auth","admin1:AdMiN123","Load Balancer(haproxy) authetication string in the format username:password",null),
|
||||||
NetworkLBHaproxyStatsPort("Network", ManagementServer.class, String.class, "network.loadbalancer.haproxy.stats.port","8081","Load Balancer(haproxy) stats port number.",null),
|
NetworkLBHaproxyStatsPort("Network", ManagementServer.class, String.class, "network.loadbalancer.haproxy.stats.port","8081","Load Balancer(haproxy) stats port number.",null),
|
||||||
@ -79,7 +79,7 @@ public enum Config {
|
|||||||
SecurityGroupWorkerThreads("Network", ManagementServer.class, Integer.class, "network.securitygroups.workers.pool.size", "50", "Number of worker threads processing the security group update work queue", null),
|
SecurityGroupWorkerThreads("Network", ManagementServer.class, Integer.class, "network.securitygroups.workers.pool.size", "50", "Number of worker threads processing the security group update work queue", null),
|
||||||
SecurityGroupWorkGlobalLockTimeout("Network", ManagementServer.class, Integer.class, "network.securitygroups.work.lock.timeout", "300", "Lock wait timeout (seconds) while updating the security group work queue", null),
|
SecurityGroupWorkGlobalLockTimeout("Network", ManagementServer.class, Integer.class, "network.securitygroups.work.lock.timeout", "300", "Lock wait timeout (seconds) while updating the security group work queue", null),
|
||||||
|
|
||||||
FirewallRuleUiEnabled("Network", ManagementServer.class, Boolean.class, "firewall.rule.ui.enabled", "true", "enable/disable UI that separates firewall rules from NAT/LB rules", null),
|
FirewallRuleUiEnabled("Network", ManagementServer.class, Boolean.class, "firewall.rule.ui.enabled", "false", "enable/disable UI that separates firewall rules from NAT/LB rules", null),
|
||||||
|
|
||||||
//VPN
|
//VPN
|
||||||
RemoteAccessVpnPskLength("Network", AgentManager.class, Integer.class, "remote.access.vpn.psk.length", "24", "The length of the ipsec preshared key (minimum 8, maximum 256)", null),
|
RemoteAccessVpnPskLength("Network", AgentManager.class, Integer.class, "remote.access.vpn.psk.length", "24", "The length of the ipsec preshared key (minimum 8, maximum 256)", null),
|
||||||
|
|||||||
@ -640,7 +640,7 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
|
|||||||
s_logger.warn("Unable to update db record for host id=" + host.getId() + "; it's possible that the host is removed");
|
s_logger.warn("Unable to update db record for host id=" + host.getId() + "; it's possible that the host is removed");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s_logger.isDebugEnabled() && result == 1) {
|
if (s_logger.isDebugEnabled() && result == 0) {
|
||||||
HostVO vo = findById(host.getId());
|
HostVO vo = findById(host.getId());
|
||||||
|
|
||||||
if (vo != null) {
|
if (vo != null) {
|
||||||
|
|||||||
@ -299,7 +299,13 @@ public class ElasticLoadBalancerManagerImpl implements
|
|||||||
cmd.lbStatsUri = _configDao.getValue(Config.NetworkLBHaproxyStatsUri.key());
|
cmd.lbStatsUri = _configDao.getValue(Config.NetworkLBHaproxyStatsUri.key());
|
||||||
cmd.lbStatsAuth = _configDao.getValue(Config.NetworkLBHaproxyStatsAuth.key());
|
cmd.lbStatsAuth = _configDao.getValue(Config.NetworkLBHaproxyStatsAuth.key());
|
||||||
cmd.lbStatsPort = _configDao.getValue(Config.NetworkLBHaproxyStatsPort.key());
|
cmd.lbStatsPort = _configDao.getValue(Config.NetworkLBHaproxyStatsPort.key());
|
||||||
cmd.lbStatsIp = elbVm.getGuestIpAddress();
|
if (cmd.lbStatsVisibility.equals("guest-network"))
|
||||||
|
{
|
||||||
|
cmd.lbStatsIp = elbVm.getGuestIpAddress();;
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
cmd.lbStatsIp = elbVm.getPrivateIpAddress();
|
||||||
|
}
|
||||||
cmds.addCommand(cmd);
|
cmds.addCommand(cmd);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2017,11 +2017,19 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
|
|||||||
}
|
}
|
||||||
|
|
||||||
LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(lbs);
|
LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(lbs);
|
||||||
cmd.lbStatsIp = router.getGuestIpAddress();
|
|
||||||
cmd.lbStatsVisibility = _configDao.getValue(Config.NetworkLBHaproxyStatsVisbility.key());
|
cmd.lbStatsVisibility = _configDao.getValue(Config.NetworkLBHaproxyStatsVisbility.key());
|
||||||
cmd.lbStatsUri = _configDao.getValue(Config.NetworkLBHaproxyStatsUri.key());
|
cmd.lbStatsUri = _configDao.getValue(Config.NetworkLBHaproxyStatsUri.key());
|
||||||
cmd.lbStatsAuth = _configDao.getValue(Config.NetworkLBHaproxyStatsAuth.key());
|
cmd.lbStatsAuth = _configDao.getValue(Config.NetworkLBHaproxyStatsAuth.key());
|
||||||
cmd.lbStatsPort = _configDao.getValue(Config.NetworkLBHaproxyStatsPort.key());
|
cmd.lbStatsPort = _configDao.getValue(Config.NetworkLBHaproxyStatsPort.key());
|
||||||
|
if (cmd.lbStatsVisibility.equals("guest-network"))
|
||||||
|
{
|
||||||
|
cmd.lbStatsIp = router.getGuestIpAddress();
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
cmd.lbStatsIp = router.getPrivateIpAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, router.getPrivateIpAddress());
|
cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, router.getPrivateIpAddress());
|
||||||
cmd.setAccessDetail(NetworkElementCommand.ROUTER_GUEST_IP, router.getGuestIpAddress());
|
cmd.setAccessDetail(NetworkElementCommand.ROUTER_GUEST_IP, router.getGuestIpAddress());
|
||||||
|
|||||||
@ -22,7 +22,6 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import com.cloud.domain.DomainVO;
|
import com.cloud.domain.DomainVO;
|
||||||
import com.cloud.hypervisor.Hypervisor;
|
|
||||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
import com.cloud.storage.VMTemplateVO;
|
import com.cloud.storage.VMTemplateVO;
|
||||||
import com.cloud.template.VirtualMachineTemplate.TemplateFilter;
|
import com.cloud.template.VirtualMachineTemplate.TemplateFilter;
|
||||||
|
|||||||
@ -249,21 +249,23 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Long extract(Account caller, Long templateId, String url, Long zoneId, String mode, Long eventId, boolean isISO, AsyncJobVO job, AsyncJobManager mgr) {
|
private Long extract(Account caller, Long templateId, String url, Long zoneId, String mode, Long eventId, boolean isISO, AsyncJobVO job, AsyncJobManager mgr) {
|
||||||
String desc = "template";
|
String desc = Upload.Type.TEMPLATE.toString();
|
||||||
if (isISO) {
|
if (isISO) {
|
||||||
desc = "ISO";
|
desc = Upload.Type.ISO.toString();
|
||||||
}
|
}
|
||||||
eventId = eventId == null ? 0:eventId;
|
eventId = eventId == null ? 0:eventId;
|
||||||
|
|
||||||
VMTemplateVO template = _tmpltDao.findById(templateId);
|
VMTemplateVO template = _tmpltDao.findById(templateId);
|
||||||
if (template == null || template.getRemoved() != null) {
|
if (template == null || template.getRemoved() != null) {
|
||||||
throw new InvalidParameterValueException("Unable to find " +desc+ " with id " + templateId);
|
throw new InvalidParameterValueException("Unable to find " +desc+ " with id " + templateId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (template.getTemplateType() == Storage.TemplateType.SYSTEM){
|
if (template.getTemplateType() == Storage.TemplateType.SYSTEM){
|
||||||
throw new InvalidParameterValueException("Unable to extract the " + desc + " " + template.getName() + " as it is a default System template");
|
throw new InvalidParameterValueException("Unable to extract the " + desc + " " + template.getName() + " as it is a default System template");
|
||||||
}
|
} else if (template.getTemplateType() == Storage.TemplateType.PERHOST){
|
||||||
if (template.getTemplateType() == Storage.TemplateType.PERHOST){
|
|
||||||
throw new InvalidParameterValueException("Unable to extract the " + desc + " " + template.getName() + " as it resides on host and not on SSVM");
|
throw new InvalidParameterValueException("Unable to extract the " + desc + " " + template.getName() + " as it resides on host and not on SSVM");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isISO) {
|
if (isISO) {
|
||||||
if (template.getFormat() != ImageFormat.ISO ){
|
if (template.getFormat() != ImageFormat.ISO ){
|
||||||
throw new InvalidParameterValueException("Unsupported format, could not extract the ISO");
|
throw new InvalidParameterValueException("Unsupported format, could not extract the ISO");
|
||||||
@ -273,6 +275,7 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
|
|||||||
throw new InvalidParameterValueException("Unsupported format, could not extract the template");
|
throw new InvalidParameterValueException("Unsupported format, could not extract the template");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_dcDao.findById(zoneId) == null) {
|
if (_dcDao.findById(zoneId) == null) {
|
||||||
throw new IllegalArgumentException("Please specify a valid zone.");
|
throw new IllegalArgumentException("Please specify a valid zone.");
|
||||||
}
|
}
|
||||||
@ -300,14 +303,15 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( tmpltHostRef == null ) {
|
if (tmpltHostRef == null ) {
|
||||||
throw new InvalidParameterValueException("The " + desc + " has not been downloaded ");
|
throw new InvalidParameterValueException("The " + desc + " has not been downloaded ");
|
||||||
}
|
}
|
||||||
|
|
||||||
Upload.Mode extractMode;
|
Upload.Mode extractMode;
|
||||||
if( mode == null || (!mode.equals(Upload.Mode.FTP_UPLOAD.toString()) && !mode.equals(Upload.Mode.HTTP_DOWNLOAD.toString())) ){
|
if (mode == null || (!mode.equalsIgnoreCase(Upload.Mode.FTP_UPLOAD.toString()) && !mode.equalsIgnoreCase(Upload.Mode.HTTP_DOWNLOAD.toString())) ){
|
||||||
throw new InvalidParameterValueException("Please specify a valid extract Mode "+Upload.Mode.values());
|
throw new InvalidParameterValueException("Please specify a valid extract Mode. Supported modes: "+ Upload.Mode.FTP_UPLOAD + ", " + Upload.Mode.HTTP_DOWNLOAD);
|
||||||
}else{
|
} else {
|
||||||
extractMode = mode.equals(Upload.Mode.FTP_UPLOAD.toString()) ? Upload.Mode.FTP_UPLOAD : Upload.Mode.HTTP_DOWNLOAD;
|
extractMode = mode.equalsIgnoreCase(Upload.Mode.FTP_UPLOAD.toString()) ? Upload.Mode.FTP_UPLOAD : Upload.Mode.HTTP_DOWNLOAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extractMode == Upload.Mode.FTP_UPLOAD){
|
if (extractMode == Upload.Mode.FTP_UPLOAD){
|
||||||
@ -334,7 +338,7 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
|
|||||||
throw new InvalidParameterValueException("Unable to resolve " + host);
|
throw new InvalidParameterValueException("Unable to resolve " + host);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( _uploadMonitor.isTypeUploadInProgress(templateId, isISO ? Type.ISO : Type.TEMPLATE) ){
|
if (_uploadMonitor.isTypeUploadInProgress(templateId, isISO ? Type.ISO : Type.TEMPLATE) ){
|
||||||
throw new IllegalArgumentException(template.getName() + " upload is in progress. Please wait for some time to schedule another upload for the same");
|
throw new IllegalArgumentException(template.getName() + " upload is in progress. Please wait for some time to schedule another upload for the same");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,7 +346,7 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
|
|||||||
}
|
}
|
||||||
|
|
||||||
UploadVO vo = _uploadMonitor.createEntityDownloadURL(template, tmpltHostRef, zoneId, eventId);
|
UploadVO vo = _uploadMonitor.createEntityDownloadURL(template, tmpltHostRef, zoneId, eventId);
|
||||||
if (vo!=null){
|
if (vo != null){
|
||||||
return vo.getId();
|
return vo.getId();
|
||||||
}else{
|
}else{
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@ -1594,13 +1594,20 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(vm.getHostId() == null || hostId != vm.getHostId()) {
|
if(serverState == State.Running) {
|
||||||
try {
|
try {
|
||||||
stateTransitTo(vm, VirtualMachine.Event.AgentReportMigrated, hostId);
|
if(hostId != vm.getHostId()) {
|
||||||
|
if (s_logger.isDebugEnabled()) {
|
||||||
|
s_logger.debug("detected host change when VM " + vm + " is at running state, VM could be live-migrated externally from host "
|
||||||
|
+ vm.getHostId() + " to host " + hostId);
|
||||||
|
}
|
||||||
|
|
||||||
|
stateTransitTo(vm, VirtualMachine.Event.AgentReportMigrated, hostId);
|
||||||
|
}
|
||||||
} catch (NoTransitionException e) {
|
} catch (NoTransitionException e) {
|
||||||
s_logger.warn(e.getMessage());
|
s_logger.warn(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (agentState == serverState) {
|
if (agentState == serverState) {
|
||||||
|
|||||||
@ -49,7 +49,7 @@ ALTER TABLE `cloud`.`configuration` ADD INDEX `i_configuration__component` (`com
|
|||||||
ALTER TABLE `cloud`.`port_forwarding_rules` ADD CONSTRAINT `fk_port_forwarding_rules__instance_id` FOREIGN KEY `fk_port_forwarding_rules__instance_id` (`instance_id`) REFERENCES `vm_instance` (`id`) ON DELETE CASCADE;
|
ALTER TABLE `cloud`.`port_forwarding_rules` ADD CONSTRAINT `fk_port_forwarding_rules__instance_id` FOREIGN KEY `fk_port_forwarding_rules__instance_id` (`instance_id`) REFERENCES `vm_instance` (`id`) ON DELETE CASCADE;
|
||||||
|
|
||||||
INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'management-server', 'agent.load.threshold', '0.70', 'Percentage (as a value between 0 and 1) of connected agents after which agent load balancing will start happening');
|
INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'management-server', 'agent.load.threshold', '0.70', 'Percentage (as a value between 0 and 1) of connected agents after which agent load balancing will start happening');
|
||||||
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.stats.visibility', 'global', 'Load Balancer(haproxy) stats visibilty, it can be global,guest-network,disabled');
|
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.stats.visibility', 'global', 'Load Balancer(haproxy) stats visibilty, it can take the following four parameters : global,guest-network,link-local,disabled');
|
||||||
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.stats.uri','/admin?stats','Load Balancer(haproxy) uri.');
|
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.stats.uri','/admin?stats','Load Balancer(haproxy) uri.');
|
||||||
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.stats.auth','admin1:AdMiN123','Load Balancer(haproxy) authetication string in the format username:password');
|
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.stats.auth','admin1:AdMiN123','Load Balancer(haproxy) authetication string in the format username:password');
|
||||||
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.stats.port','8081','Load Balancer(haproxy) stats port number.');
|
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.stats.port','8081','Load Balancer(haproxy) stats port number.');
|
||||||
|
|||||||
@ -27,11 +27,11 @@ ALTER TABLE `cloud`.`firewall_rules` ADD CONSTRAINT `fk_firewall_rules__related`
|
|||||||
ALTER TABLE `cloud`.`firewall_rules` MODIFY `start_port` int(10) COMMENT 'starting port of a port range';
|
ALTER TABLE `cloud`.`firewall_rules` MODIFY `start_port` int(10) COMMENT 'starting port of a port range';
|
||||||
ALTER TABLE `cloud`.`firewall_rules` MODIFY `end_port` int(10) COMMENT 'end port of a port range';
|
ALTER TABLE `cloud`.`firewall_rules` MODIFY `end_port` int(10) COMMENT 'end port of a port range';
|
||||||
|
|
||||||
INSERT IGNORE INTO `cloud`.`configuration` (category, instance, name, value, description) VALUES ('Network', 'DEFAULT', 'firewall.rule.ui.enabled', 'true', 'enable/disable UI that separates firewall rules from NAT/LB rules');
|
INSERT IGNORE INTO `cloud`.`configuration` (category, instance, name, value, description) VALUES ('Network', 'DEFAULT', 'firewall.rule.ui.enabled', 'false', 'enable/disable UI that separates firewall rules from NAT/LB rules');
|
||||||
|
|
||||||
|
|
||||||
INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'management-server', 'agent.load.threshold', '0.70', 'Percentage (as a value between 0 and 1) of connected agents after which agent load balancing will start happening');
|
INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'management-server', 'agent.load.threshold', '0.70', 'Percentage (as a value between 0 and 1) of connected agents after which agent load balancing will start happening');
|
||||||
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.stats.visibility', 'global', 'Load Balancer(haproxy) stats visibilty, it can be global,guest-network,disabled');
|
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.stats.visibility', 'global', 'Load Balancer(haproxy) stats visibilty, it can take the following four parameters : global,guest-network,link-local,disabled');
|
||||||
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.stats.uri','/admin?stats','Load Balancer(haproxy) uri.');
|
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.stats.uri','/admin?stats','Load Balancer(haproxy) uri.');
|
||||||
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.stats.auth','admin1:AdMiN123','Load Balancer(haproxy) authetication string in the format username:password');
|
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.stats.auth','admin1:AdMiN123','Load Balancer(haproxy) authetication string in the format username:password');
|
||||||
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.stats.port','8081','Load Balancer(haproxy) stats port number.');
|
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.stats.port','8081','Load Balancer(haproxy) stats port number.');
|
||||||
|
|||||||
@ -4,6 +4,8 @@ import time
|
|||||||
import Queue
|
import Queue
|
||||||
import copy
|
import copy
|
||||||
import sys
|
import sys
|
||||||
|
import jsonHelper
|
||||||
|
import datetime
|
||||||
|
|
||||||
class job(object):
|
class job(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -17,51 +19,81 @@ class jobStatus(object):
|
|||||||
self.endTime = None
|
self.endTime = None
|
||||||
self.duration = None
|
self.duration = None
|
||||||
self.jobId = None
|
self.jobId = None
|
||||||
|
self.responsecls = None
|
||||||
class workThread(threading.Thread):
|
class workThread(threading.Thread):
|
||||||
def __init__(self, in_queue, out_dict, apiClient, db=None):
|
def __init__(self, in_queue, outqueue, apiClient, db=None, lock=None):
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
self.inqueue = in_queue
|
self.inqueue = in_queue
|
||||||
self.output = out_dict
|
self.output = outqueue
|
||||||
self.connection = copy.copy(apiClient.connection)
|
self.connection = apiClient.connection
|
||||||
self.db = None
|
self.db = None
|
||||||
|
self.lock = lock
|
||||||
|
|
||||||
|
def queryAsynJob(self, job):
|
||||||
|
if job.jobId is None:
|
||||||
|
return job
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.lock.acquire()
|
||||||
|
result = self.connection.pollAsyncJob(job.jobId, job.responsecls).jobresult
|
||||||
|
except cloudstackException.cloudstackAPIException, e:
|
||||||
|
result = str(e)
|
||||||
|
finally:
|
||||||
|
self.lock.release()
|
||||||
|
|
||||||
|
job.result = result
|
||||||
|
return job
|
||||||
|
|
||||||
|
def executeCmd(self, job):
|
||||||
|
cmd = job.cmd
|
||||||
|
|
||||||
|
jobstatus = jobStatus()
|
||||||
|
jobId = None
|
||||||
|
try:
|
||||||
|
self.lock.acquire()
|
||||||
|
|
||||||
|
if cmd.isAsync == "false":
|
||||||
|
jobstatus.startTime = datetime.datetime.now()
|
||||||
|
|
||||||
|
result = self.connection.make_request(cmd)
|
||||||
|
jobstatus.result = result
|
||||||
|
jobstatus.endTime = datetime.datetime.now()
|
||||||
|
jobstatus.duration = time.mktime(jobstatus.endTime.timetuple()) - time.mktime(jobstatus.startTime.timetuple())
|
||||||
|
else:
|
||||||
|
result = self.connection.make_request(cmd, None, True)
|
||||||
|
if result is None:
|
||||||
|
jobstatus.status = False
|
||||||
|
else:
|
||||||
|
jobId = result.jobid
|
||||||
|
jobstatus.jobId = jobId
|
||||||
|
try:
|
||||||
|
responseName = cmd.__class__.__name__.replace("Cmd", "Response")
|
||||||
|
jobstatus.responsecls = jsonHelper.getclassFromName(cmd, responseName)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
jobstatus.status = True
|
||||||
|
except cloudstackException.cloudstackAPIException, e:
|
||||||
|
jobstatus.result = str(e)
|
||||||
|
jobstatus.status = False
|
||||||
|
except:
|
||||||
|
jobstatus.status = False
|
||||||
|
jobstatus.result = sys.exc_info()
|
||||||
|
finally:
|
||||||
|
self.lock.release()
|
||||||
|
|
||||||
|
return jobstatus
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
while self.inqueue.qsize() > 0:
|
while self.inqueue.qsize() > 0:
|
||||||
job = self.inqueue.get()
|
job = self.inqueue.get()
|
||||||
cmd = job.cmd
|
if isinstance(job, jobStatus):
|
||||||
cmdName = cmd.__class__.__name__
|
jobstatus = self.queryAsynJob(job)
|
||||||
responseName = cmdName.replace("Cmd", "Response")
|
else:
|
||||||
responseInstance = self.connection.getclassFromName(cmd, responseName)
|
jobstatus = self.executeCmd(job)
|
||||||
jobstatus = jobStatus()
|
|
||||||
jobId = None
|
|
||||||
try:
|
|
||||||
if not cmd.isAsync:
|
|
||||||
jobstatus.startTime = time.time()
|
|
||||||
result = self.connection.make_request(cmd, responseInstance)
|
|
||||||
jobstatus.result = result
|
|
||||||
jobstatus.endTime = time.time()
|
|
||||||
else:
|
|
||||||
result = self.connection.make_request(cmd, responseInstance, True)
|
|
||||||
jobId = self.connection.getAsyncJobId(responseInstance, result)
|
|
||||||
result = self.connection.pollAsyncJob(cmd, responseInstance, jobId)
|
|
||||||
jobstatus.result = result
|
|
||||||
jobstatus.jobId = jobId
|
|
||||||
|
|
||||||
jobstatus.status = True
|
self.output.put(jobstatus)
|
||||||
except cloudstackException.cloudstackAPIException, e:
|
|
||||||
jobstatus.result = str(e)
|
|
||||||
jobstatus.status = False
|
|
||||||
except:
|
|
||||||
jobstatus.status = False
|
|
||||||
jobstatus.result = sys.exc_info()
|
|
||||||
|
|
||||||
#print job.id
|
|
||||||
self.output.lock.acquire()
|
|
||||||
self.output.dict[job.id] = jobstatus
|
|
||||||
self.output.lock.release()
|
|
||||||
self.inqueue.task_done()
|
self.inqueue.task_done()
|
||||||
|
|
||||||
|
|
||||||
'''release the resource'''
|
'''release the resource'''
|
||||||
self.connection.close()
|
self.connection.close()
|
||||||
|
|
||||||
@ -92,6 +124,7 @@ class asyncJobMgr(object):
|
|||||||
def __init__(self, apiClient, db):
|
def __init__(self, apiClient, db):
|
||||||
self.inqueue = Queue.Queue()
|
self.inqueue = Queue.Queue()
|
||||||
self.output = outputDict()
|
self.output = outputDict()
|
||||||
|
self.outqueue = Queue.Queue()
|
||||||
self.apiClient = apiClient
|
self.apiClient = apiClient
|
||||||
self.db = db
|
self.db = db
|
||||||
|
|
||||||
@ -109,34 +142,48 @@ class asyncJobMgr(object):
|
|||||||
ids.append(id)
|
ids.append(id)
|
||||||
return ids
|
return ids
|
||||||
|
|
||||||
def waitForComplete(self):
|
def updateTimeStamp(self, jobstatus):
|
||||||
self.inqueue.join()
|
jobId = jobstatus.jobId
|
||||||
|
if jobId is not None and self.db is not None:
|
||||||
for k,jobstatus in self.output.dict.iteritems():
|
result = self.db.execute("select job_status, created, last_updated from async_job where id=%s"%jobId)
|
||||||
jobId = jobstatus.jobId
|
if result is not None and len(result) > 0:
|
||||||
if jobId is not None and self.db is not None:
|
if result[0][0] == 1:
|
||||||
result = self.db.execute("select job_status, created, last_updated from async_job where id=%s"%jobId)
|
jobstatus.status = True
|
||||||
if result is not None and len(result) > 0:
|
else:
|
||||||
if result[0][0] == 1:
|
jobstatus.status = False
|
||||||
jobstatus.status = True
|
|
||||||
else:
|
|
||||||
jobstatus.status = False
|
|
||||||
jobstatus.startTime = result[0][1]
|
jobstatus.startTime = result[0][1]
|
||||||
jobstatus.endTime = result[0][2]
|
jobstatus.endTime = result[0][2]
|
||||||
delta = jobstatus.endTime - jobstatus.startTime
|
delta = jobstatus.endTime - jobstatus.startTime
|
||||||
jobstatus.duration = delta.total_seconds()
|
jobstatus.duration = delta.total_seconds()
|
||||||
|
|
||||||
|
def waitForComplete(self, workers=10):
|
||||||
|
self.inqueue.join()
|
||||||
|
lock = threading.Lock()
|
||||||
|
resultQueue = Queue.Queue()
|
||||||
|
'''intermediate result is stored in self.outqueue'''
|
||||||
|
for i in range(workers):
|
||||||
|
worker = workThread(self.outqueue, resultQueue, self.apiClient, self.db, lock)
|
||||||
|
worker.start()
|
||||||
|
|
||||||
return self.output.dict
|
self.outqueue.join()
|
||||||
|
|
||||||
|
asyncJobResult = []
|
||||||
|
while resultQueue.qsize() > 0:
|
||||||
|
jobstatus = resultQueue.get()
|
||||||
|
self.updateTimeStamp(jobstatus)
|
||||||
|
asyncJobResult.append(jobstatus)
|
||||||
|
|
||||||
|
return asyncJobResult
|
||||||
|
|
||||||
'''put commands into a queue at first, then start workers numbers threads to execute this commands'''
|
'''put commands into a queue at first, then start workers numbers threads to execute this commands'''
|
||||||
def submitCmdsAndWait(self, cmds, workers=10):
|
def submitCmdsAndWait(self, cmds, workers=10):
|
||||||
self.submitCmds(cmds)
|
self.submitCmds(cmds)
|
||||||
|
lock = threading.Lock()
|
||||||
for i in range(workers):
|
for i in range(workers):
|
||||||
worker = workThread(self.inqueue, self.output, self.apiClient, self.db)
|
worker = workThread(self.inqueue, self.outqueue, self.apiClient, self.db, lock)
|
||||||
worker.start()
|
worker.start()
|
||||||
|
|
||||||
return self.waitForComplete()
|
return self.waitForComplete(workers)
|
||||||
|
|
||||||
'''submit one job and execute the same job ntimes, with nums_threads of threads'''
|
'''submit one job and execute the same job ntimes, with nums_threads of threads'''
|
||||||
def submitJobExecuteNtimes(self, job, ntimes=1, nums_threads=1, interval=1):
|
def submitJobExecuteNtimes(self, job, ntimes=1, nums_threads=1, interval=1):
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import time
|
|||||||
import inspect
|
import inspect
|
||||||
import cloudstackException
|
import cloudstackException
|
||||||
from cloudstackAPI import *
|
from cloudstackAPI import *
|
||||||
|
import jsonHelper
|
||||||
|
|
||||||
class cloudConnection(object):
|
class cloudConnection(object):
|
||||||
def __init__(self, mgtSvr, port=8096, apiKey = None, securityKey = None, asyncTimeout=3600, logging=None):
|
def __init__(self, mgtSvr, port=8096, apiKey = None, securityKey = None, asyncTimeout=3600, logging=None):
|
||||||
@ -38,7 +39,7 @@ class cloudConnection(object):
|
|||||||
def make_request_with_auth(self, command, requests={}):
|
def make_request_with_auth(self, command, requests={}):
|
||||||
requests["command"] = command
|
requests["command"] = command
|
||||||
requests["apiKey"] = self.apiKey
|
requests["apiKey"] = self.apiKey
|
||||||
requests["response"] = "xml"
|
requests["response"] = "json"
|
||||||
requests = zip(requests.keys(), requests.values())
|
requests = zip(requests.keys(), requests.values())
|
||||||
requests.sort(key=lambda x: str.lower(x[0]))
|
requests.sort(key=lambda x: str.lower(x[0]))
|
||||||
|
|
||||||
@ -54,148 +55,30 @@ class cloudConnection(object):
|
|||||||
|
|
||||||
def make_request_without_auth(self, command, requests={}):
|
def make_request_without_auth(self, command, requests={}):
|
||||||
requests["command"] = command
|
requests["command"] = command
|
||||||
requests["response"] = "xml"
|
requests["response"] = "json"
|
||||||
requests = zip(requests.keys(), requests.values())
|
requests = zip(requests.keys(), requests.values())
|
||||||
requestUrl = "&".join(["=".join([request[0], urllib.quote_plus(str(request[1]))]) for request in requests])
|
requestUrl = "&".join(["=".join([request[0], urllib.quote_plus(str(request[1]))]) for request in requests])
|
||||||
self.connection.request("GET", "/&%s"%requestUrl)
|
self.connection.request("GET", "/&%s"%requestUrl)
|
||||||
return self.connection.getresponse().read()
|
return self.connection.getresponse().read()
|
||||||
|
|
||||||
def getText(self, elements):
|
def pollAsyncJob(self, jobId, response):
|
||||||
if len(elements) < 1:
|
|
||||||
return None
|
|
||||||
if not elements[0].hasChildNodes():
|
|
||||||
return None
|
|
||||||
if elements[0].childNodes[0].nodeValue is None:
|
|
||||||
return None
|
|
||||||
return elements[0].childNodes[0].nodeValue.strip()
|
|
||||||
|
|
||||||
def getclassFromName(self, cmd, name):
|
|
||||||
module = inspect.getmodule(cmd)
|
|
||||||
return getattr(module, name)()
|
|
||||||
def parseOneInstance(self, element, instance):
|
|
||||||
ItemsNeedToCheck = {}
|
|
||||||
for attribute in dir(instance):
|
|
||||||
if attribute != "__doc__" and attribute != "__init__" and attribute != "__module__":
|
|
||||||
ItemsNeedToCheck[attribute] = getattr(instance, attribute)
|
|
||||||
for attribute, value in ItemsNeedToCheck.items():
|
|
||||||
if type(value) == types.ListType:
|
|
||||||
subItem = []
|
|
||||||
for subElement in element.getElementsByTagName(attribute):
|
|
||||||
newInstance = self.getclassFromName(instance, attribute)
|
|
||||||
self.parseOneInstance(subElement, newInstance)
|
|
||||||
subItem.append(newInstance)
|
|
||||||
setattr(instance, attribute, subItem)
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
item = element.getElementsByTagName(attribute)
|
|
||||||
if len(item) == 0:
|
|
||||||
continue
|
|
||||||
|
|
||||||
returnValue = self.getText(item)
|
|
||||||
setattr(instance, attribute, returnValue)
|
|
||||||
|
|
||||||
def hasErrorCode(self, elements, responseName):
|
|
||||||
errorCode = elements[0].getElementsByTagName("errorcode")
|
|
||||||
if len(errorCode) > 0:
|
|
||||||
erroCodeText = self.getText(errorCode)
|
|
||||||
errorText = elements[0].getElementsByTagName("errortext")
|
|
||||||
if len(errorText) > 0:
|
|
||||||
errorText = self.getText(errorText)
|
|
||||||
errMsg = "errorCode: %s, errorText:%s"%(erroCodeText, errorText)
|
|
||||||
raise cloudstackException.cloudstackAPIException(responseName, errMsg)
|
|
||||||
|
|
||||||
def paraseReturnXML(self, result, response):
|
|
||||||
responseName = response.__class__.__name__.lower()
|
|
||||||
cls = response.__class__
|
|
||||||
|
|
||||||
responseLists = []
|
|
||||||
morethanOne = False
|
|
||||||
|
|
||||||
dom = xml.dom.minidom.parseString(result)
|
|
||||||
elements = dom.getElementsByTagName(responseName)
|
|
||||||
if len(elements) == 0:
|
|
||||||
return responseLists
|
|
||||||
|
|
||||||
self.hasErrorCode(elements, responseName)
|
|
||||||
|
|
||||||
count = elements[0].getElementsByTagName("count")
|
|
||||||
if len(count) > 0:
|
|
||||||
morethanOne = True
|
|
||||||
for node in elements[0].childNodes:
|
|
||||||
if node.nodeName == "count":
|
|
||||||
continue
|
|
||||||
newInstance = cls()
|
|
||||||
self.parseOneInstance(node, newInstance)
|
|
||||||
responseLists.append(newInstance)
|
|
||||||
|
|
||||||
else:
|
|
||||||
if elements[0].hasChildNodes():
|
|
||||||
newInstance = cls()
|
|
||||||
self.parseOneInstance(elements[0], newInstance)
|
|
||||||
responseLists.append(newInstance)
|
|
||||||
|
|
||||||
return responseLists, morethanOne
|
|
||||||
|
|
||||||
def paraseResultFromElement(self, elements, response):
|
|
||||||
responseName = response.__class__.__name__.lower()
|
|
||||||
cls = response.__class__
|
|
||||||
|
|
||||||
responseLists = []
|
|
||||||
morethanOne = False
|
|
||||||
|
|
||||||
newInstance = cls()
|
|
||||||
self.parseOneInstance(elements[0], newInstance)
|
|
||||||
responseLists.append(newInstance)
|
|
||||||
|
|
||||||
return responseLists, morethanOne
|
|
||||||
def getAsyncJobId(self, response, resultXml):
|
|
||||||
responseName = response.__class__.__name__.lower()
|
|
||||||
dom = xml.dom.minidom.parseString(resultXml)
|
|
||||||
elements = dom.getElementsByTagName(responseName)
|
|
||||||
if len(elements) == 0:
|
|
||||||
raise cloudstackException.cloudstackAPIException("can't find %s"%responseName)
|
|
||||||
|
|
||||||
self.hasErrorCode(elements, responseName)
|
|
||||||
|
|
||||||
jobIdEle = elements[0].getElementsByTagName("jobid")
|
|
||||||
if len(jobIdEle) == 0:
|
|
||||||
errMsg = 'can not find jobId in the result:%s'%resultXml
|
|
||||||
|
|
||||||
raise cloudstackException.cloudstackAPIException(errMsg)
|
|
||||||
|
|
||||||
jobId = self.getText(jobIdEle)
|
|
||||||
return jobId
|
|
||||||
|
|
||||||
def pollAsyncJob(self, cmd, response, jobId):
|
|
||||||
commandName = cmd.__class__.__name__.replace("Cmd", "")
|
|
||||||
cmd = queryAsyncJobResult.queryAsyncJobResultCmd()
|
cmd = queryAsyncJobResult.queryAsyncJobResultCmd()
|
||||||
cmd.jobid = jobId
|
cmd.jobid = jobId
|
||||||
|
|
||||||
while self.asyncTimeout > 0:
|
while self.asyncTimeout > 0:
|
||||||
asyncResponse = queryAsyncJobResult.queryAsyncJobResultResponse()
|
asyncResonse = self.make_request(cmd, response, True)
|
||||||
responseName = asyncResponse.__class__.__name__.lower()
|
|
||||||
asyncResponseXml = self.make_request(cmd, asyncResponse, True)
|
|
||||||
dom = xml.dom.minidom.parseString(asyncResponseXml)
|
|
||||||
elements = dom.getElementsByTagName(responseName)
|
|
||||||
if len(elements) == 0:
|
|
||||||
raise cloudstackException.cloudstackAPIException("can't find %s"%responseName)
|
|
||||||
|
|
||||||
self.hasErrorCode(elements, responseName)
|
|
||||||
|
|
||||||
jobstatus = self.getText(elements[0].getElementsByTagName("jobstatus"))
|
if asyncResonse.jobstatus == 2:
|
||||||
|
raise cloudstackException.cloudstackAPIException("asyncquery", asyncResonse.jobresult)
|
||||||
|
elif asyncResonse.jobstatus == 1:
|
||||||
|
return asyncResonse
|
||||||
|
|
||||||
if jobstatus == "2":
|
|
||||||
jobResult = self.getText(elements[0].getElementsByTagName("jobresult"))
|
|
||||||
raise cloudstackException.cloudstackAPIException(commandName, jobResult)
|
|
||||||
elif jobstatus == "1":
|
|
||||||
jobResultEle = elements[0].getElementsByTagName("jobresult")
|
|
||||||
|
|
||||||
return self.paraseResultFromElement(jobResultEle, response)
|
|
||||||
|
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
|
self.asyncTimeout = self.asyncTimeout - 5
|
||||||
|
|
||||||
raise cloudstackException.cloudstackAPIException(commandName, "Async job timeout")
|
raise cloudstackException.cloudstackAPIException("asyncquery", "Async job timeout")
|
||||||
def make_request(self, cmd, response, raw=False):
|
|
||||||
|
def make_request(self, cmd, response = None, raw=False):
|
||||||
commandName = cmd.__class__.__name__.replace("Cmd", "")
|
commandName = cmd.__class__.__name__.replace("Cmd", "")
|
||||||
isAsync = "false"
|
isAsync = "false"
|
||||||
requests = {}
|
requests = {}
|
||||||
@ -231,7 +114,7 @@ class cloudConnection(object):
|
|||||||
i = i + 1
|
i = i + 1
|
||||||
|
|
||||||
if self.logging is not None:
|
if self.logging is not None:
|
||||||
self.logging.debug("sending command: " + str(requests))
|
self.logging.debug("sending command: %s %s"%(commandName, str(requests)))
|
||||||
result = None
|
result = None
|
||||||
if self.auth:
|
if self.auth:
|
||||||
result = self.make_request_with_auth(commandName, requests)
|
result = self.make_request_with_auth(commandName, requests)
|
||||||
@ -243,19 +126,13 @@ class cloudConnection(object):
|
|||||||
if result is None:
|
if result is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if raw:
|
result = jsonHelper.getResultObj(result, response)
|
||||||
return result
|
if raw or isAsync == "false":
|
||||||
if isAsync == "false":
|
|
||||||
result,num = self.paraseReturnXML(result, response)
|
|
||||||
else:
|
|
||||||
jobId = self.getAsyncJobId(response, result)
|
|
||||||
result,num = self.pollAsyncJob(cmd, response, jobId)
|
|
||||||
if num:
|
|
||||||
return result
|
return result
|
||||||
else:
|
else:
|
||||||
if len(result) != 0:
|
asynJobId = result.jobid
|
||||||
return result[0]
|
result = self.pollAsyncJob(asynJobId, response)
|
||||||
return None
|
return result.jobresult
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
xml = '<?xml version="1.0" encoding="ISO-8859-1"?><deployVirtualMachineResponse><virtualmachine><id>407</id><name>i-1-407-RS3</name><displayname>i-1-407-RS3</displayname><account>system</account><domainid>1</domainid><domain>ROOT</domain><created>2011-07-30T14:45:19-0700</created><state>Running</state><haenable>false</haenable><zoneid>1</zoneid><zonename>CA1</zonename><hostid>3</hostid><hostname>kvm-50-205</hostname><templateid>4</templateid><templatename>CentOS 5.5(64-bit) no GUI (KVM)</templatename><templatedisplaytext>CentOS 5.5(64-bit) no GUI (KVM)</templatedisplaytext><passwordenabled>false</passwordenabled><serviceofferingid>1</serviceofferingid><serviceofferingname>Small Instance</serviceofferingname><cpunumber>1</cpunumber><cpuspeed>500</cpuspeed><memory>512</memory><guestosid>112</guestosid><rootdeviceid>0</rootdeviceid><rootdevicetype>NetworkFilesystem</rootdevicetype><nic><id>380</id><networkid>203</networkid><netmask>255.255.255.0</netmask><gateway>65.19.181.1</gateway><ipaddress>65.19.181.110</ipaddress><isolationuri>vlan://65</isolationuri><broadcasturi>vlan://65</broadcasturi><traffictype>Guest</traffictype><type>Direct</type><isdefault>true</isdefault><macaddress>06:52:da:00:00:08</macaddress></nic><hypervisor>KVM</hypervisor></virtualmachine></deployVirtualMachineResponse>'
|
xml = '<?xml version="1.0" encoding="ISO-8859-1"?><deployVirtualMachineResponse><virtualmachine><id>407</id><name>i-1-407-RS3</name><displayname>i-1-407-RS3</displayname><account>system</account><domainid>1</domainid><domain>ROOT</domain><created>2011-07-30T14:45:19-0700</created><state>Running</state><haenable>false</haenable><zoneid>1</zoneid><zonename>CA1</zonename><hostid>3</hostid><hostname>kvm-50-205</hostname><templateid>4</templateid><templatename>CentOS 5.5(64-bit) no GUI (KVM)</templatename><templatedisplaytext>CentOS 5.5(64-bit) no GUI (KVM)</templatedisplaytext><passwordenabled>false</passwordenabled><serviceofferingid>1</serviceofferingid><serviceofferingname>Small Instance</serviceofferingname><cpunumber>1</cpunumber><cpuspeed>500</cpuspeed><memory>512</memory><guestosid>112</guestosid><rootdeviceid>0</rootdeviceid><rootdevicetype>NetworkFilesystem</rootdevicetype><nic><id>380</id><networkid>203</networkid><netmask>255.255.255.0</netmask><gateway>65.19.181.1</gateway><ipaddress>65.19.181.110</ipaddress><isolationuri>vlan://65</isolationuri><broadcasturi>vlan://65</broadcasturi><traffictype>Guest</traffictype><type>Direct</type><isdefault>true</isdefault><macaddress>06:52:da:00:00:08</macaddress></nic><hypervisor>KVM</hypervisor></virtualmachine></deployVirtualMachineResponse>'
|
||||||
|
|||||||
@ -39,7 +39,8 @@ class cloudstackTestClient(object):
|
|||||||
def getApiClient(self):
|
def getApiClient(self):
|
||||||
return self.apiClient
|
return self.apiClient
|
||||||
|
|
||||||
def submitCmdsAndWait(self, cmds, workers=10):
|
'''FixME, httplib has issue if more than one thread submitted'''
|
||||||
|
def submitCmdsAndWait(self, cmds, workers=1):
|
||||||
if self.asyncJobMgr is None:
|
if self.asyncJobMgr is None:
|
||||||
self.asyncJobMgr = asyncJobMgr.asyncJobMgr(self.apiClient, self.dbConnection)
|
self.asyncJobMgr = asyncJobMgr.asyncJobMgr(self.apiClient, self.dbConnection)
|
||||||
return self.asyncJobMgr.submitCmdsAndWait(cmds, workers)
|
return self.asyncJobMgr.submitCmdsAndWait(cmds, workers)
|
||||||
|
|||||||
@ -1,57 +1,7 @@
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
class Struct:
|
import jsonHelper
|
||||||
'''The recursive class for building and representing objects with.'''
|
|
||||||
def __init__(self, obj):
|
|
||||||
for k in obj:
|
|
||||||
v = obj[k]
|
|
||||||
if isinstance(v, dict):
|
|
||||||
setattr(self, k, Struct(v))
|
|
||||||
elif isinstance(v, (list, tuple)):
|
|
||||||
setattr(self, k, [Struct(elem) for elem in v])
|
|
||||||
else:
|
|
||||||
setattr(self,k,v)
|
|
||||||
def __getattr__(self, val):
|
|
||||||
if val in self.__dict__:
|
|
||||||
return self.__dict__[val]
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
def __repr__(self):
|
|
||||||
return '{%s}' % str(', '.join('%s : %s' % (k, repr(v)) for (k, v) in self.__dict__.iteritems()))
|
|
||||||
|
|
||||||
|
|
||||||
def json_repr(obj):
|
|
||||||
"""Represent instance of a class as JSON.
|
|
||||||
Arguments:
|
|
||||||
obj -- any object
|
|
||||||
Return:
|
|
||||||
String that reprent JSON-encoded object.
|
|
||||||
"""
|
|
||||||
def serialize(obj):
|
|
||||||
"""Recursively walk object's hierarchy."""
|
|
||||||
if isinstance(obj, (bool, int, long, float, basestring)):
|
|
||||||
return obj
|
|
||||||
elif isinstance(obj, dict):
|
|
||||||
obj = obj.copy()
|
|
||||||
newobj = {}
|
|
||||||
for key in obj:
|
|
||||||
if obj[key] is not None:
|
|
||||||
if (isinstance(obj[key], list) and len(obj[key]) == 0):
|
|
||||||
continue
|
|
||||||
newobj[key] = serialize(obj[key])
|
|
||||||
|
|
||||||
return newobj
|
|
||||||
elif isinstance(obj, list):
|
|
||||||
return [serialize(item) for item in obj]
|
|
||||||
elif isinstance(obj, tuple):
|
|
||||||
return tuple(serialize([item for item in obj]))
|
|
||||||
elif hasattr(obj, '__dict__'):
|
|
||||||
return serialize(obj.__dict__)
|
|
||||||
else:
|
|
||||||
return repr(obj) # Don't know how to handle, convert to string
|
|
||||||
return serialize(obj)
|
|
||||||
|
|
||||||
class managementServer():
|
class managementServer():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.mgtSvrIp = None
|
self.mgtSvrIp = None
|
||||||
@ -199,7 +149,7 @@ def describe_setup_in_basic_mode():
|
|||||||
p.name = "test" +str(l) + str(i)
|
p.name = "test" +str(l) + str(i)
|
||||||
p.gateway = "192.168.%d.1"%i
|
p.gateway = "192.168.%d.1"%i
|
||||||
p.netmask = "255.255.255.0"
|
p.netmask = "255.255.255.0"
|
||||||
p.startip = "192.168.%d.200"%i
|
p.startip = "192.168.%d.150"%i
|
||||||
p.endip = "192.168.%d.220"%i
|
p.endip = "192.168.%d.220"%i
|
||||||
|
|
||||||
'''add two pod guest ip ranges'''
|
'''add two pod guest ip ranges'''
|
||||||
@ -399,10 +349,10 @@ def describe_setup_in_advanced_mode():
|
|||||||
def generate_setup_config(config, file=None):
|
def generate_setup_config(config, file=None):
|
||||||
describe = config
|
describe = config
|
||||||
if file is None:
|
if file is None:
|
||||||
return json.dumps(json_repr(describe))
|
return json.dumps(jsonHelper.jsonDump.dump(describe))
|
||||||
else:
|
else:
|
||||||
fp = open(file, 'w')
|
fp = open(file, 'w')
|
||||||
json.dump(json_repr(describe), fp, indent=4)
|
json.dump(jsonHelper.jsonDump.dump(describe), fp, indent=4)
|
||||||
fp.close()
|
fp.close()
|
||||||
|
|
||||||
|
|
||||||
@ -412,7 +362,7 @@ def get_setup_config(file):
|
|||||||
config = cloudstackConfiguration()
|
config = cloudstackConfiguration()
|
||||||
fp = open(file, 'r')
|
fp = open(file, 'r')
|
||||||
config = json.load(fp)
|
config = json.load(fp)
|
||||||
return Struct(config)
|
return jsonHelper.jsonLoader(config)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
parser = OptionParser()
|
parser = OptionParser()
|
||||||
|
|||||||
169
tools/testClient/jsonHelper.py
Normal file
169
tools/testClient/jsonHelper.py
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
import cloudstackException
|
||||||
|
import json
|
||||||
|
import inspect
|
||||||
|
from cloudstackAPI import *
|
||||||
|
class jsonLoader:
|
||||||
|
'''The recursive class for building and representing objects with.'''
|
||||||
|
def __init__(self, obj):
|
||||||
|
for k in obj:
|
||||||
|
v = obj[k]
|
||||||
|
if isinstance(v, dict):
|
||||||
|
setattr(self, k, jsonLoader(v))
|
||||||
|
elif isinstance(v, (list, tuple)):
|
||||||
|
setattr(self, k, [jsonLoader(elem) for elem in v])
|
||||||
|
else:
|
||||||
|
setattr(self,k,v)
|
||||||
|
def __getattr__(self, val):
|
||||||
|
if val in self.__dict__:
|
||||||
|
return self.__dict__[val]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
def __repr__(self):
|
||||||
|
return '{%s}' % str(', '.join('%s : %s' % (k, repr(v)) for (k, v) in self.__dict__.iteritems()))
|
||||||
|
def __str__(self):
|
||||||
|
return '{%s}' % str(', '.join('%s : %s' % (k, repr(v)) for (k, v) in self.__dict__.iteritems()))
|
||||||
|
|
||||||
|
|
||||||
|
class jsonDump:
|
||||||
|
@staticmethod
|
||||||
|
def __serialize(obj):
|
||||||
|
"""Recursively walk object's hierarchy."""
|
||||||
|
if isinstance(obj, (bool, int, long, float, basestring)):
|
||||||
|
return obj
|
||||||
|
elif isinstance(obj, dict):
|
||||||
|
obj = obj.copy()
|
||||||
|
newobj = {}
|
||||||
|
for key in obj:
|
||||||
|
if obj[key] is not None:
|
||||||
|
if (isinstance(obj[key], list) and len(obj[key]) == 0):
|
||||||
|
continue
|
||||||
|
newobj[key] = jsonDump.__serialize(obj[key])
|
||||||
|
|
||||||
|
return newobj
|
||||||
|
elif isinstance(obj, list):
|
||||||
|
return [jsonDump.__serialize(item) for item in obj]
|
||||||
|
elif isinstance(obj, tuple):
|
||||||
|
return tuple(jsonDump.__serialize([item for item in obj]))
|
||||||
|
elif hasattr(obj, '__dict__'):
|
||||||
|
return jsonDump.__serialize(obj.__dict__)
|
||||||
|
else:
|
||||||
|
return repr(obj) # Don't know how to handle, convert to string
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def dump(obj):
|
||||||
|
return jsonDump.__serialize(obj)
|
||||||
|
|
||||||
|
def getclassFromName(cmd, name):
|
||||||
|
module = inspect.getmodule(cmd)
|
||||||
|
return getattr(module, name)()
|
||||||
|
|
||||||
|
def finalizeResultObj(result, responseName, responsecls):
|
||||||
|
if responsecls is None and responseName.endswith("response") and responseName != "queryasyncjobresultresponse":
|
||||||
|
'''infer the response class from the name'''
|
||||||
|
moduleName = responseName.replace("response", "")
|
||||||
|
try:
|
||||||
|
responsecls = getclassFromName(moduleName, responseName)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if responseName is not None and responseName == "queryasyncjobresultresponse" and responsecls is not None and result.jobresult is not None:
|
||||||
|
result.jobresult = finalizeResultObj(result.jobresult, None, responsecls)
|
||||||
|
return result
|
||||||
|
elif responsecls is not None:
|
||||||
|
for k,v in result.__dict__.iteritems():
|
||||||
|
if k in responsecls.__dict__:
|
||||||
|
return result
|
||||||
|
|
||||||
|
attr = result.__dict__.keys()[0]
|
||||||
|
|
||||||
|
value = getattr(result, attr)
|
||||||
|
if not isinstance(value, jsonLoader):
|
||||||
|
return result
|
||||||
|
|
||||||
|
findObj = False
|
||||||
|
for k,v in value.__dict__.iteritems():
|
||||||
|
if k in responsecls.__dict__:
|
||||||
|
findObj = True
|
||||||
|
break
|
||||||
|
if findObj:
|
||||||
|
return value
|
||||||
|
else:
|
||||||
|
return result
|
||||||
|
else:
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def getResultObj(returnObj, responsecls=None):
|
||||||
|
returnObj = json.loads(returnObj)
|
||||||
|
|
||||||
|
if len(returnObj) == 0:
|
||||||
|
return None
|
||||||
|
responseName = returnObj.keys()[0]
|
||||||
|
|
||||||
|
response = returnObj[responseName]
|
||||||
|
if len(response) == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
result = jsonLoader(response)
|
||||||
|
if result.errorcode is not None:
|
||||||
|
errMsg = "errorCode: %s, errorText:%s"%(result.errorcode, result.errortext)
|
||||||
|
raise cloudstackException.cloudstackAPIException(responseName.replace("response", ""), errMsg)
|
||||||
|
|
||||||
|
if result.count is not None:
|
||||||
|
for key in result.__dict__.iterkeys():
|
||||||
|
if key == "count":
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
return getattr(result, key)
|
||||||
|
else:
|
||||||
|
return finalizeResultObj(result, responseName, responsecls)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
result = '{ "listzonesresponse" : { "count":1 ,"zone" : [ {"id":1,"name":"test0","dns1":"8.8.8.8","dns2":"4.4.4.4","internaldns1":"192.168.110.254","internaldns2":"192.168.110.253","networktype":"Basic","securitygroupsenabled":true,"allocationstate":"Enabled","zonetoken":"5e818a11-6b00-3429-9a07-e27511d3169a","dhcpprovider":"DhcpServer"} ] } }'
|
||||||
|
zones = getResultObj(result)
|
||||||
|
print zones[0].id
|
||||||
|
res = authorizeSecurityGroupIngress.authorizeSecurityGroupIngressResponse()
|
||||||
|
result = '{ "queryasyncjobresultresponse" : {"jobid":10,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"securitygroup":{"id":1,"name":"default","description":"Default Security Group","account":"admin","domainid":1,"domain":"ROOT","ingressrule":[{"ruleid":1,"protocol":"tcp","startport":22,"endport":22,"securitygroupname":"default","account":"a"},{"ruleid":2,"protocol":"tcp","startport":22,"endport":22,"securitygroupname":"default","account":"b"}]}}} }'
|
||||||
|
asynJob = getResultObj(result, res)
|
||||||
|
print asynJob.jobid, repr(asynJob.jobresult)
|
||||||
|
print asynJob.jobresult.ingressrule[0].account
|
||||||
|
|
||||||
|
result = '{ "queryasyncjobresultresponse" : {"errorcode" : 431, "errortext" : "Unable to execute API command queryasyncjobresultresponse due to missing parameter jobid"} }'
|
||||||
|
try:
|
||||||
|
asynJob = getResultObj(result)
|
||||||
|
except cloudstackException.cloudstackAPIException, e:
|
||||||
|
print e
|
||||||
|
|
||||||
|
result = '{ "queryasyncjobresultresponse" : {} }'
|
||||||
|
asynJob = getResultObj(result)
|
||||||
|
print asynJob
|
||||||
|
|
||||||
|
result = '{}'
|
||||||
|
asynJob = getResultObj(result)
|
||||||
|
print asynJob
|
||||||
|
|
||||||
|
result = '{ "createzoneresponse" : { "zone" : {"id":1,"name":"test0","dns1":"8.8.8.8","dns2":"4.4.4.4","internaldns1":"192.168.110.254","internaldns2":"192.168.110.253","networktype":"Basic","securitygroupsenabled":true,"allocationstate":"Enabled","zonetoken":"3442f287-e932-3111-960b-514d1f9c4610","dhcpprovider":"DhcpServer"} } }'
|
||||||
|
res = createZone.createZoneResponse()
|
||||||
|
zone = getResultObj(result, res)
|
||||||
|
print zone.id
|
||||||
|
|
||||||
|
result = '{ "attachvolumeresponse" : {"jobid":24} }'
|
||||||
|
res = attachVolume.attachVolumeResponse()
|
||||||
|
res = getResultObj(result, res)
|
||||||
|
print res
|
||||||
|
|
||||||
|
result = '{ "listtemplatesresponse" : { } }'
|
||||||
|
print getResultObj(result, listTemplates.listTemplatesResponse())
|
||||||
|
|
||||||
|
result = '{ "queryasyncjobresultresponse" : {"jobid":34,"jobstatus":2,"jobprocstatus":0,"jobresultcode":530,"jobresulttype":"object","jobresult":{"errorcode":431,"errortext":"Please provide either a volume id, or a tuple(device id, instance id)"}} }'
|
||||||
|
print getResultObj(result, listTemplates.listTemplatesResponse())
|
||||||
|
result = '{ "queryasyncjobresultresponse" : {"jobid":41,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":37,"name":"i-2-37-TEST","displayname":"i-2-37-TEST","account":"admin","domainid":1,"domain":"ROOT","created":"2011-08-25T11:13:42-0700","state":"Running","haenable":false,"zoneid":1,"zonename":"test0","hostid":5,"hostname":"SimulatedAgent.1e629060-f547-40dd-b792-57cdc4b7d611","templateid":10,"templatename":"CentOS 5.3(64-bit) no GUI (Simulator)","templatedisplaytext":"CentOS 5.3(64-bit) no GUI (Simulator)","passwordenabled":false,"serviceofferingid":7,"serviceofferingname":"Small Instance","cpunumber":1,"cpuspeed":500,"memory":512,"guestosid":11,"rootdeviceid":0,"rootdevicetype":"NetworkFilesystem","securitygroup":[{"id":1,"name":"default","description":"Default Security Group"}],"nic":[{"id":43,"networkid":204,"netmask":"255.255.255.0","gateway":"192.168.1.1","ipaddress":"192.168.1.27","isolationuri":"ec2://untagged","broadcasturi":"vlan://untagged","traffictype":"Guest","type":"Direct","isdefault":true,"macaddress":"06:56:b8:00:00:53"}],"hypervisor":"Simulator"}}} }'
|
||||||
|
vm = getResultObj(result, deployVirtualMachine.deployVirtualMachineResponse())
|
||||||
|
print vm.jobresult.id
|
||||||
|
|
||||||
|
cmd = deployVirtualMachine.deployVirtualMachineCmd()
|
||||||
|
responsename = cmd.__class__.__name__.replace("Cmd", "Response")
|
||||||
|
response = getclassFromName(cmd, responsename)
|
||||||
|
print response.id
|
||||||
@ -10,7 +10,7 @@ class TestCase1(cloudstackTestCase):
|
|||||||
listtmcmd.templatefilter = "featured"
|
listtmcmd.templatefilter = "featured"
|
||||||
listtmresponse = apiClient.listTemplates(listtmcmd)
|
listtmresponse = apiClient.listTemplates(listtmcmd)
|
||||||
if listtmresponse is not None and len(listtmresponse) > 0:
|
if listtmresponse is not None and len(listtmresponse) > 0:
|
||||||
self.debug(listtmresponse[0].isready)
|
self.debug(listtmresponse)
|
||||||
self.debug("we are here")
|
self.debug("we are here")
|
||||||
else:
|
else:
|
||||||
self.debug("we are there")
|
self.debug("we are there")
|
||||||
|
|||||||
@ -7,5 +7,17 @@ class TestCase2(cloudstackTestCase):
|
|||||||
listtmcmd.id = 10
|
listtmcmd.id = 10
|
||||||
listtmcmd.zoneid = 1
|
listtmcmd.zoneid = 1
|
||||||
listtmcmd.templatefilter = "featured"
|
listtmcmd.templatefilter = "featured"
|
||||||
listtmresponse = apiClient.listTemplates(listtmcmd)
|
#listtmresponse = apiClient.listTemplates(listtmcmd)
|
||||||
self.debug(listtmresponse[0].isready)
|
#self.debug(listtmresponse[0].isready)
|
||||||
|
|
||||||
|
listhostcmd=listHosts.listHostsCmd()
|
||||||
|
listhostcmd.zoneid=1
|
||||||
|
listhostcmd.type="Routing"
|
||||||
|
|
||||||
|
asyncJobResult=self.testClient.submitCmdsAndWait([listhostcmd],1)
|
||||||
|
listVMresponse = asyncJobResult[0].result
|
||||||
|
self.debug("Total Number of Hosts: " + str(len(listVMresponse)))
|
||||||
|
|
||||||
|
for i in listVMresponse:
|
||||||
|
self.debug("id: " + str(i.id) +" pod id: " + str(i.podid) +" host tag: " + str(i.hosttags))
|
||||||
|
|
||||||
@ -21,11 +21,11 @@ class TestCase1(cloudstackTestCase):
|
|||||||
tmpls = self.testClient.getApiClient().listTemplates(listtmplcmd)
|
tmpls = self.testClient.getApiClient().listTemplates(listtmplcmd)
|
||||||
if tmpls is not None:
|
if tmpls is not None:
|
||||||
for tmpl in tmpls:
|
for tmpl in tmpls:
|
||||||
if tmpl.isready == "true":
|
if tmpl.isready:
|
||||||
self.templateId = tmpl.id
|
self.templateId = tmpl.id
|
||||||
self.zoneId = tmpl.zoneid
|
self.zoneId = tmpl.zoneid
|
||||||
break
|
break
|
||||||
|
|
||||||
def test_cloudstackapi(self):
|
def test_cloudstackapi(self):
|
||||||
apiClient = self.testClient.getApiClient()
|
apiClient = self.testClient.getApiClient()
|
||||||
|
|
||||||
@ -52,14 +52,34 @@ class TestCase1(cloudstackTestCase):
|
|||||||
'''
|
'''
|
||||||
cidrlist = ["192.168.1.1/24", "10.1.1.1/24"]
|
cidrlist = ["192.168.1.1/24", "10.1.1.1/24"]
|
||||||
securitygroup.cidrlist = cidrlist
|
securitygroup.cidrlist = cidrlist
|
||||||
apiClient.authorizeSecurityGroupIngress(securitygroup)
|
try:
|
||||||
|
apiClient.authorizeSecurityGroupIngress(securitygroup)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
'''
|
||||||
createvm = deployVirtualMachine.deployVirtualMachineCmd()
|
createvm = deployVirtualMachine.deployVirtualMachineCmd()
|
||||||
createvm.serviceofferingid = self.svid
|
createvm.serviceofferingid = self.svid
|
||||||
createvm.templateid = self.templateId
|
createvm.templateid = self.templateId
|
||||||
createvm.zoneid = self.zoneId
|
createvm.zoneid = self.zoneId
|
||||||
vm = apiClient.deployVirtualMachine(createvm)
|
vm = apiClient.deployVirtualMachine(createvm)
|
||||||
vmId = vm.id
|
vmId = vm.id
|
||||||
|
'''
|
||||||
|
vmId = 1
|
||||||
|
vmcmds = []
|
||||||
|
for i in range(10):
|
||||||
|
createvm = deployVirtualMachine.deployVirtualMachineCmd()
|
||||||
|
createvm.serviceofferingid = self.svid
|
||||||
|
createvm.templateid = self.templateId
|
||||||
|
createvm.zoneid = self.zoneId
|
||||||
|
vmcmds.append(createvm)
|
||||||
|
|
||||||
|
result = self.testClient.submitCmdsAndWait(vmcmds, 5)
|
||||||
|
for jobstatus in result:
|
||||||
|
if jobstatus.status == 1:
|
||||||
|
self.debug(jobstatus.result.id)
|
||||||
|
self.debug(jobstatus.result.displayname)
|
||||||
|
else:
|
||||||
|
self.debug(jobstatus.result)
|
||||||
|
|
||||||
creatvolume = createVolume.createVolumeCmd()
|
creatvolume = createVolume.createVolumeCmd()
|
||||||
creatvolume.name = "tetst" + str(uuid.uuid4())
|
creatvolume.name = "tetst" + str(uuid.uuid4())
|
||||||
|
|||||||
@ -49,7 +49,7 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
asyncJobResult = testclient.submitCmdsAndWait(cmds, 6)
|
asyncJobResult = testclient.submitCmdsAndWait(cmds, 6)
|
||||||
|
|
||||||
for handle, jobStatus in asyncJobResult.iteritems():
|
for jobStatus in asyncJobResult:
|
||||||
if jobStatus.status:
|
if jobStatus.status:
|
||||||
print jobStatus.result[0].id, jobStatus.result[0].templatename, jobStatus.startTime, jobStatus.endTime
|
print jobStatus.result[0].id, jobStatus.result[0].templatename, jobStatus.startTime, jobStatus.endTime
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -74,7 +74,7 @@ a:hover {
|
|||||||
width:181px;
|
width:181px;
|
||||||
height:66px;
|
height:66px;
|
||||||
float:left;
|
float:left;
|
||||||
background:url(../images/login_logo.gif) no-repeat top left;
|
background:url(../images/login_logo.png) no-repeat top left;
|
||||||
margin:0 0 0 75px;
|
margin:0 0 0 75px;
|
||||||
display:inline;
|
display:inline;
|
||||||
padding:0;
|
padding:0;
|
||||||
@ -1391,7 +1391,7 @@ a:hover {
|
|||||||
width:106px;
|
width:106px;
|
||||||
height:37px;
|
height:37px;
|
||||||
float:left;
|
float:left;
|
||||||
background:url(../images/logo.gif) no-repeat top left;
|
background:url(../images/logo.png) no-repeat top left;
|
||||||
margin:0 0 0 8px;
|
margin:0 0 0 8px;
|
||||||
display:inline;
|
display:inline;
|
||||||
padding:0;
|
padding:0;
|
||||||
@ -3261,7 +3261,7 @@ a:hover.search_button {
|
|||||||
width:132px;
|
width:132px;
|
||||||
height:22px;
|
height:22px;
|
||||||
float:right;
|
float:right;
|
||||||
background:url(../images/poweredby.gif) no-repeat top left;
|
/*background:url(../images/poweredby.gif) no-repeat top left;*/
|
||||||
margin:2px 10px 0 0;
|
margin:2px 10px 0 0;
|
||||||
padding:0;
|
padding:0;
|
||||||
display:inline;
|
display:inline;
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.1 KiB |
BIN
ui/images/login_logo.png
Normal file
BIN
ui/images/login_logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.0 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.3 KiB |
BIN
ui/images/logo.png
Normal file
BIN
ui/images/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
<script language="javascript">
|
<script language="javascript">
|
||||||
dictionary = {
|
dictionary = {
|
||||||
|
'label.action.edit.host' : '<fmt:message key="label.action.edit.host"/>',
|
||||||
'label.action.enable.maintenance.mode' : '<fmt:message key="label.action.enable.maintenance.mode"/>',
|
'label.action.enable.maintenance.mode' : '<fmt:message key="label.action.enable.maintenance.mode"/>',
|
||||||
'label.action.enable.maintenance.mode.processing' : '<fmt:message key="label.action.enable.maintenance.mode.processing"/>',
|
'label.action.enable.maintenance.mode.processing' : '<fmt:message key="label.action.enable.maintenance.mode.processing"/>',
|
||||||
'message.action.host.enable.maintenance.mode' : '<fmt:message key="message.action.host.enable.maintenance.mode"/>',
|
'message.action.host.enable.maintenance.mode' : '<fmt:message key="message.action.host.enable.maintenance.mode"/>',
|
||||||
@ -120,6 +121,8 @@ dictionary = {
|
|||||||
<div class="grid_row_cell" style="width: 79%;">
|
<div class="grid_row_cell" style="width: 79%;">
|
||||||
<div class="row_celltitles" id="hosttags">
|
<div class="row_celltitles" id="hosttags">
|
||||||
</div>
|
</div>
|
||||||
|
<input class="text" id="hosttags_edit" style="width: 200px; display: none;" type="text" />
|
||||||
|
<div id="hosttags_edit_errormsg" style="display:none"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid_rows odd">
|
<div class="grid_rows odd">
|
||||||
@ -189,7 +192,9 @@ dictionary = {
|
|||||||
</div>
|
</div>
|
||||||
<div class="grid_row_cell" style="width: 79%;">
|
<div class="grid_row_cell" style="width: 79%;">
|
||||||
<div class="row_celltitles" id="oscategoryname">
|
<div class="row_celltitles" id="oscategoryname">
|
||||||
</div>
|
</div>
|
||||||
|
<select class="select" id="os_dropdown" style="width: 202px; display: none;">
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid_rows even">
|
<div class="grid_rows even">
|
||||||
@ -202,7 +207,14 @@ dictionary = {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="grid_botactionpanel">
|
||||||
|
<div class="gridbot_buttons" id="save_button" style="display:none;"><fmt:message key="label.save"/></div>
|
||||||
|
<div class="gridbot_buttons" id="cancel_button" style="display:none;"><fmt:message key="label.cancel"/></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Details tab (end)-->
|
<!-- Details tab (end)-->
|
||||||
|
|||||||
@ -61,7 +61,25 @@ function afterLoadHostJSP() {
|
|||||||
var tabContentArray = [$("#tab_content_details"), $("#tab_content_instance"), $("#tab_content_router"), $("#tab_content_systemvm"), $("#tab_content_statistics")];
|
var tabContentArray = [$("#tab_content_details"), $("#tab_content_instance"), $("#tab_content_router"), $("#tab_content_systemvm"), $("#tab_content_statistics")];
|
||||||
var afterSwitchFnArray = [hostJsonToDetailsTab, hostJsonToInstanceTab, hostJsonToRouterTab, hostJsonToSystemvmTab, hostJsonToStatisticsTab];
|
var afterSwitchFnArray = [hostJsonToDetailsTab, hostJsonToInstanceTab, hostJsonToRouterTab, hostJsonToSystemvmTab, hostJsonToStatisticsTab];
|
||||||
switchBetweenDifferentTabs(tabArray, tabContentArray, afterSwitchFnArray);
|
switchBetweenDifferentTabs(tabArray, tabContentArray, afterSwitchFnArray);
|
||||||
|
|
||||||
|
$readonlyFields = $("#tab_content_details").find("#hosttags,#oscategoryname");
|
||||||
|
$editFields = $("#tab_content_details").find("#hosttags_edit,#os_dropdown");
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
data: createURL("command=listOsCategories"),
|
||||||
|
dataType: "json",
|
||||||
|
success: function(json) {
|
||||||
|
var categories = json.listoscategoriesresponse.oscategory;
|
||||||
|
var $dropdown = $("#tab_content_details").find("#os_dropdown").empty();
|
||||||
|
$dropdown.append("<option value=''>None</option>");
|
||||||
|
if (categories != null && categories.length > 0) {
|
||||||
|
for (var i = 0; i < categories.length; i++) {
|
||||||
|
$dropdown.append("<option value='" + categories[i].id + "'>" + fromdb(categories[i].name) + "</option>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
hostRefreshDataBinding();
|
hostRefreshDataBinding();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,43 +221,45 @@ function hostBuildActionMenu(jsonObj, $thisTab, $midmenuItem1) {
|
|||||||
$actionMenu.find("#action_list").empty();
|
$actionMenu.find("#action_list").empty();
|
||||||
var noAvailableActions = true;
|
var noAvailableActions = true;
|
||||||
|
|
||||||
if (jsonObj.state == 'Up' || jsonObj.state == "Connecting") {
|
if (jsonObj.state == 'Up' || jsonObj.state == "Connecting") {
|
||||||
|
buildActionLinkForTab("label.action.edit.host", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
||||||
buildActionLinkForTab("label.action.enable.maintenance.mode", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
buildActionLinkForTab("label.action.enable.maintenance.mode", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
||||||
buildActionLinkForTab("label.action.force.reconnect", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
buildActionLinkForTab("label.action.force.reconnect", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
||||||
buildActionLinkForTab("label.action.update.OS.preference", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
buildActionLinkForTab("label.action.update.OS.preference", hostActionMap, $actionMenu, $midmenuItem1, $thisTab); //temp
|
||||||
noAvailableActions = false;
|
noAvailableActions = false;
|
||||||
}
|
}
|
||||||
else if(jsonObj.state == 'Down') {
|
else if(jsonObj.state == 'Down') {
|
||||||
buildActionLinkForTab("label.action.enable.maintenance.mode", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
buildActionLinkForTab("label.action.edit.host", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
||||||
buildActionLinkForTab("label.action.update.OS.preference", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
buildActionLinkForTab("label.action.enable.maintenance.mode", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
||||||
buildActionLinkForTab("label.action.remove.host", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
buildActionLinkForTab("label.action.remove.host", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
||||||
noAvailableActions = false;
|
noAvailableActions = false;
|
||||||
}
|
}
|
||||||
else if(jsonObj.state == "Alert") {
|
else if(jsonObj.state == "Alert") {
|
||||||
buildActionLinkForTab("label.action.update.OS.preference", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
buildActionLinkForTab("label.action.edit.host", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
||||||
buildActionLinkForTab("label.action.remove.host", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
buildActionLinkForTab("label.action.remove.host", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
||||||
noAvailableActions = false;
|
noAvailableActions = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (jsonObj.state == "ErrorInMaintenance") {
|
else if (jsonObj.state == "ErrorInMaintenance") {
|
||||||
|
buildActionLinkForTab("label.action.edit.host", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
||||||
buildActionLinkForTab("label.action.enable.maintenance.mode", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
buildActionLinkForTab("label.action.enable.maintenance.mode", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
||||||
buildActionLinkForTab("label.action.cancel.maintenance.mode", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
buildActionLinkForTab("label.action.cancel.maintenance.mode", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
||||||
buildActionLinkForTab("label.action.update.OS.preference", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
|
||||||
noAvailableActions = false;
|
noAvailableActions = false;
|
||||||
}
|
}
|
||||||
else if (jsonObj.state == "PrepareForMaintenance") {
|
else if (jsonObj.state == "PrepareForMaintenance") {
|
||||||
buildActionLinkForTab("label.action.cancel.maintenance.mode", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
buildActionLinkForTab("label.action.edit.host", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
||||||
buildActionLinkForTab("label.action.update.OS.preference", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
buildActionLinkForTab("label.action.cancel.maintenance.mode", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
||||||
noAvailableActions = false;
|
noAvailableActions = false;
|
||||||
}
|
}
|
||||||
else if (jsonObj.state == "Maintenance") {
|
else if (jsonObj.state == "Maintenance") {
|
||||||
buildActionLinkForTab("label.action.cancel.maintenance.mode", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
buildActionLinkForTab("label.action.edit.host", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
||||||
buildActionLinkForTab("label.action.update.OS.preference", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
buildActionLinkForTab("label.action.cancel.maintenance.mode", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
||||||
buildActionLinkForTab("label.action.remove.host", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
buildActionLinkForTab("label.action.remove.host", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
||||||
noAvailableActions = false;
|
noAvailableActions = false;
|
||||||
}
|
}
|
||||||
else if (jsonObj.state == "Disconnected"){
|
else if (jsonObj.state == "Disconnected"){
|
||||||
buildActionLinkForTab("label.action.update.OS.preference", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
buildActionLinkForTab("label.action.edit.host", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
||||||
buildActionLinkForTab("label.action.remove.host", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
buildActionLinkForTab("label.action.remove.host", hostActionMap, $actionMenu, $midmenuItem1, $thisTab);
|
||||||
noAvailableActions = false;
|
noAvailableActions = false;
|
||||||
}
|
}
|
||||||
@ -548,6 +568,9 @@ function populateForUpdateOSDialog(oscategoryid) {
|
|||||||
|
|
||||||
|
|
||||||
var hostActionMap = {
|
var hostActionMap = {
|
||||||
|
"label.action.edit.host": {
|
||||||
|
dialogBeforeActionFn: doEditHost
|
||||||
|
},
|
||||||
"label.action.enable.maintenance.mode": {
|
"label.action.enable.maintenance.mode": {
|
||||||
isAsyncJob: true,
|
isAsyncJob: true,
|
||||||
asyncJobResponse: "preparehostformaintenanceresponse",
|
asyncJobResponse: "preparehostformaintenanceresponse",
|
||||||
@ -604,6 +627,59 @@ var hostActionMap = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function doEditHost($actionLink, $detailsTab, $midmenuItem1) {
|
||||||
|
var jsonObj = $midmenuItem1.data("jsonObj");
|
||||||
|
$detailsTab.find("#os_dropdown").val(jsonObj.oscategoryid);
|
||||||
|
|
||||||
|
$readonlyFields.hide();
|
||||||
|
$editFields.show();
|
||||||
|
$detailsTab.find("#cancel_button, #save_button").show();
|
||||||
|
|
||||||
|
$detailsTab.find("#cancel_button").unbind("click").bind("click", function(event){
|
||||||
|
cancelEditMode($detailsTab);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
$detailsTab.find("#save_button").unbind("click").bind("click", function(event){
|
||||||
|
doEditHost2($actionLink, $detailsTab, $midmenuItem1, $readonlyFields, $editFields);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function doEditHost2($actionLink, $detailsTab, $midmenuItem1, $readonlyFields, $editFields) {
|
||||||
|
var isValid = true;
|
||||||
|
isValid &= validateString("Host Tags", $detailsTab.find("#hosttags_edit"), $detailsTab.find("#hosttags_edit_errormsg"), true); //optional
|
||||||
|
if (!isValid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var jsonObj = $midmenuItem1.data("jsonObj");
|
||||||
|
var id = jsonObj.id;
|
||||||
|
|
||||||
|
var array1 = [];
|
||||||
|
array1.push("&id="+id);
|
||||||
|
|
||||||
|
var hosttags = $detailsTab.find("#hosttags_edit").val();
|
||||||
|
array1.push("&hosttags="+todb(hosttags));
|
||||||
|
|
||||||
|
var osCategoryId = $detailsTab.find("#os_dropdown").val();
|
||||||
|
if (osCategoryId != null && osCategoryId.length > 0)
|
||||||
|
array1.push("&osCategoryId="+osCategoryId);
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
data: createURL("command=updateHost"+array1.join("")),
|
||||||
|
dataType: "json",
|
||||||
|
async: false,
|
||||||
|
success: function(json) {
|
||||||
|
var jsonObj = json.updatehostresponse.host;
|
||||||
|
hostToMidmenu(jsonObj, $midmenuItem1);
|
||||||
|
hostToRightPanel($midmenuItem1);
|
||||||
|
|
||||||
|
$editFields.hide();
|
||||||
|
$readonlyFields.show();
|
||||||
|
$("#save_button, #cancel_button").hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function doEnableMaintenanceMode($actionLink, $detailsTab, $midmenuItem1){
|
function doEnableMaintenanceMode($actionLink, $detailsTab, $midmenuItem1){
|
||||||
var jsonObj = $midmenuItem1.data("jsonObj");
|
var jsonObj = $midmenuItem1.data("jsonObj");
|
||||||
|
|
||||||
|
|||||||
@ -81,6 +81,7 @@ import com.vmware.vim25.VirtualMachineSnapshotInfo;
|
|||||||
import com.vmware.vim25.VirtualMachineSnapshotTree;
|
import com.vmware.vim25.VirtualMachineSnapshotTree;
|
||||||
import com.vmware.vim25.VirtualPCIController;
|
import com.vmware.vim25.VirtualPCIController;
|
||||||
import com.vmware.vim25.VirtualSCSIController;
|
import com.vmware.vim25.VirtualSCSIController;
|
||||||
|
import com.vmware.vim25.VirtualSCSISharing;
|
||||||
|
|
||||||
public class VirtualMachineMO extends BaseMO {
|
public class VirtualMachineMO extends BaseMO {
|
||||||
private static final Logger s_logger = Logger.getLogger(VirtualMachineMO.class);
|
private static final Logger s_logger = Logger.getLogger(VirtualMachineMO.class);
|
||||||
@ -1526,7 +1527,43 @@ public class VirtualMachineMO extends BaseMO {
|
|||||||
assert(false);
|
assert(false);
|
||||||
throw new Exception("SCSI Controller Not Found");
|
throw new Exception("SCSI Controller Not Found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getScsiDeviceControllerKeyNoException() throws Exception {
|
||||||
|
VirtualDevice[] devices = (VirtualDevice [])_context.getServiceUtil().
|
||||||
|
getDynamicProperty(_mor, "config.hardware.device");
|
||||||
|
|
||||||
|
if(devices != null && devices.length > 0) {
|
||||||
|
for(VirtualDevice device : devices) {
|
||||||
|
if(device instanceof VirtualLsiLogicController) {
|
||||||
|
return device.getKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ensureScsiDeviceController() throws Exception {
|
||||||
|
int scsiControllerKey = getScsiDeviceControllerKeyNoException();
|
||||||
|
if(scsiControllerKey < 0) {
|
||||||
|
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||||
|
|
||||||
|
// Scsi controller
|
||||||
|
VirtualLsiLogicController scsiController = new VirtualLsiLogicController();
|
||||||
|
scsiController.setSharedBus(VirtualSCSISharing.noSharing);
|
||||||
|
scsiController.setBusNumber(0);
|
||||||
|
scsiController.setKey(1);
|
||||||
|
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||||
|
scsiControllerSpec.setDevice(scsiController);
|
||||||
|
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.add);
|
||||||
|
|
||||||
|
vmConfig.setDeviceChange(new VirtualDeviceConfigSpec[] { scsiControllerSpec });
|
||||||
|
if(configureVm(vmConfig)) {
|
||||||
|
throw new Exception("Unable to add Scsi controller");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// return pair of VirtualDisk and disk device bus name(ide0:0, etc)
|
// return pair of VirtualDisk and disk device bus name(ide0:0, etc)
|
||||||
public Pair<VirtualDisk, String> getDiskDevice(String vmdkDatastorePath, boolean matchExactly) throws Exception {
|
public Pair<VirtualDisk, String> getDiskDevice(String vmdkDatastorePath, boolean matchExactly) throws Exception {
|
||||||
VirtualDevice[] devices = (VirtualDevice[])_context.getServiceUtil().getDynamicProperty(_mor, "config.hardware.device");
|
VirtualDevice[] devices = (VirtualDevice[])_context.getServiceUtil().getDynamicProperty(_mor, "config.hardware.device");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user