Merge branch 'master' of ssh://git.cloud.com/var/lib/git/cloudstack-oss

This commit is contained in:
David Nalley 2011-08-28 23:43:28 -04:00
commit 6d101d554e
47 changed files with 620 additions and 320 deletions

View File

@ -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

View File

@ -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

View File

@ -4,6 +4,8 @@
#Labels #Labels
label.action.edit.host=ホストを編集する
network.rate=ネットワーク速度 network.rate=ネットワーク速度
ICMP.type=ICMPタイプ ICMP.type=ICMPタイプ

View File

@ -4,6 +4,8 @@
#Labels #Labels
label.action.edit.host=编辑主机
network.rate=网络速率 network.rate=网络速率
ICMP.type=ICMP类型 ICMP.type=ICMP类型

View File

@ -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;

View File

@ -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
View File

@ -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>

Binary file not shown.

BIN
deps/cloud-commons-codec-1.5.jar vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
deps/cloud-commons-dbcp-1.4.jar vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

BIN
deps/cloud-gson.jar vendored

Binary file not shown.

BIN
deps/cloud-httpclient-4.1.2.jar vendored Normal file

Binary file not shown.

View 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
}

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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),

View File

@ -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) {

View File

@ -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);
} }

View File

@ -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());

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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.');

View File

@ -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.');

View File

@ -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):

View File

@ -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>'

View File

@ -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)

View File

@ -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()

View 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

View File

@ -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")

View File

@ -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))

View File

@ -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())

View File

@ -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:

View File

@ -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

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -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)-->

View File

@ -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");

View File

@ -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");