Merge branch 'master' into vpc

Conflicts:
	server/src/com/cloud/network/rules/RulesManagerImpl.java
	server/src/com/cloud/vm/UserVmManagerImpl.java
	server/src/com/cloud/vm/VirtualMachineGuru.java
This commit is contained in:
Alena Prokharchyk 2012-07-27 13:47:46 -07:00
commit a39fd61249
90 changed files with 2323 additions and 635 deletions

View File

@ -352,12 +352,12 @@ public class MockVmManagerImpl implements MockVmManager {
_mockAgentMgr.handleSystemVMStop(vm.getId()); _mockAgentMgr.handleSystemVMStop(vm.getId());
} }
return new StopAnswer(cmd, null, new Integer(0), new Long(100), new Long(200)); return new StopAnswer(cmd, null, new Integer(0), true);
} }
@Override @Override
public Answer rebootVM(RebootCommand cmd) { public Answer rebootVM(RebootCommand cmd) {
return new RebootAnswer(cmd, "Rebooted "+cmd.getVmName()); return new RebootAnswer(cmd, "Rebooted "+cmd.getVmName(), false);
} }
@Override @Override

View File

@ -233,10 +233,10 @@ public class AgentRoutingResource extends AgentStorageResource {
Answer result = _simMgr.simulate(cmd, hostGuid); Answer result = _simMgr.simulate(cmd, hostGuid);
if (!result.getResult()) { if (!result.getResult()) {
return new StopAnswer(cmd, result.getDetails()); return new StopAnswer(cmd, result.getDetails(), false);
} }
answer = new StopAnswer(cmd, null, 0, new Long(100), new Long(200)); answer = new StopAnswer(cmd, null, 0, true);
Pair<Long, Long> data = _runningVms.get(vmName); Pair<Long, Long> data = _runningVms.get(vmName);
if (data != null) { if (data != null) {
this.usedCpu -= data.first(); this.usedCpu -= data.first();

View File

@ -1,12 +1,17 @@
#!/bin/bash #!/bin/bash
### BEGIN INIT INFO ### BEGIN INIT INFO
# Provides: cloud agent # Provides: cloud agent
# Required-Start: $network # Required-Start: $network $local_fs
# Required-Stop: $network # Required-Stop: $network $local_fs
# Default-Start: 3 4 5 # Default-Start: 3 4 5
# Default-Stop: 0 1 2 6 # Default-Stop: 0 1 2 6
# X-Interactive: true # Short-Description: Start/stop Apache CloudStack Agent
# Short-Description: Start/stop apache2 web server # Description: This scripts Starts/Stops the Apache CloudStack agent
## The CloudStack Agent is a part of the Apache CloudStack project and is used
## for managing KVM-based Hypervisors and performing secondary storage tasks inside
## the Secondary Storage System Virtual Machine.
## JSVC (Java daemonizing) is used for starting and stopping the agent
### END INIT INFO ### END INIT INFO
# Licensed to the Apache Software Foundation (ASF) under one # Licensed to the Apache Software Foundation (ASF) under one
@ -26,21 +31,17 @@
# specific language governing permissions and limitations # specific language governing permissions and limitations
# under the License. # under the License.
# WARNING: if this script is changed, then all other initscripts MUST BE changed to match it as well
. /lib/lsb/init-functions . /lib/lsb/init-functions
. /etc/default/rcS
whatami=cloud-agent SHORTNAME="cloud-agent"
PIDFILE=@PIDDIR@/"$SHORTNAME".pid
# set environment variables
SHORTNAME="$whatami"
PIDFILE=@PIDDIR@/"$whatami".pid
LOCKFILE=@LOCKDIR@/"$SHORTNAME" LOCKFILE=@LOCKDIR@/"$SHORTNAME"
LOGFILE=@AGENTLOG@ LOGFILE=@AGENTLOG@
PROGNAME="Cloud Agent" PROGNAME="CloudStack Agent"
CLASS="com.cloud.agent.AgentShell" CLASS="com.cloud.agent.AgentShell"
PROG="jsvc"
DAEMON="/usr/bin/jsvc"
SHUTDOWN_WAIT="30"
unset OPTIONS unset OPTIONS
[ -r @SYSCONFDIR@/default/"$SHORTNAME" ] && source @SYSCONFDIR@/default/"$SHORTNAME" [ -r @SYSCONFDIR@/default/"$SHORTNAME" ] && source @SYSCONFDIR@/default/"$SHORTNAME"
@ -81,53 +82,53 @@ wait_for_network() {
} }
start() { start() {
log_daemon_msg $"Starting $PROGNAME" "$SHORTNAME" if [ -s "$PIDFILE" ] && kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then
if [ -s "$PIDFILE" ] && kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then log_daemon_msg "$PROGNAME apparently already running"
log_progress_msg "apparently already running" log_end_msg 0
log_end_msg 0 exit 0
exit 0 fi
fi
if hostname --fqdn >/dev/null 2>&1 ; then
true
else
log_failure_msg "The host name does not resolve properly to an IP address. Cannot start $PROGNAME"
log_end_msg 1
exit 1
fi
wait_for_network log_daemon_msg "Starting $PROGNAME" "$SHORTNAME"
if hostname --fqdn >/dev/null 2>&1 ; then
true
else
log_failure_msg "The host name does not resolve properly to an IP address. Cannot start $PROGNAME"
log_end_msg 1
exit 1
fi
if jsvc -cp "$CLASSPATH" -pidfile "$PIDFILE" $CLASS wait_for_network
RETVAL=$?
then
rc=0
sleep 1
if ! kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then
log_failure_msg "$PROG failed to start"
rc=1
fi
else
rc=1
fi
if [ $rc -eq 0 ]; then if start_daemon -p $PIDFILE $DAEMON -cp "$CLASSPATH" -pidfile "$PIDFILE" $CLASS
log_end_msg 0 RETVAL=$?
else then
log_end_msg 1 rc=0
rm -f "$PIDFILE" sleep 1
fi if ! kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then
log_failure_msg "$PROG failed to start"
rc=1
fi
else
rc=1
fi
if [ $rc -eq 0 ]; then
log_end_msg 0
else
log_end_msg 1
rm -f "$PIDFILE"
fi
} }
stop() { stop() {
SHUTDOWN_WAIT="30"
count="0" count="0"
echo -n $"Stopping $PROGNAME" "$SHORTNAME" log_daemon_msg "Stopping $PROGNAME" "$SHORTNAME"
jsvc -pidfile "$PIDFILE" -stop $CLASS killproc -p $PIDFILE $DAEMON
until [ "$count" -gt "$SHUTDOWN_WAIT" ] until [ "$count" -gt "$SHUTDOWN_WAIT" ]
do do
agentPid=`ps aux|grep [j]svc|grep cloud-agent` agentPid=$(ps aux|grep [j]svc|grep $SHORTNAME)
if [ "$?" -gt "0" ];then if [ "$?" -gt "0" ];then
break break
fi fi
@ -135,40 +136,38 @@ stop() {
let count="${count}+1" let count="${count}+1"
done done
agentPid=`ps aux|grep [j]svc|grep cloud-agent` agentPid=$(ps aux|grep [j]svc|grep $SHORTNAME)
if [ "$?" -eq "0" ]; then if [ "$?" -eq "0" ]; then
agentPid=`ps aux|grep [j]svc|awk '{print $2}'` agentPid=$(ps aux|grep [j]svc|awk '{print $2}')
if [ "$agentPid" != "" ]; then if [ "$agentPid" != "" ]; then
kill -9 $agentPid log_warning_msg "$PROG still running, forcing kill"
fi kill -9 $agentPid
fi
fi fi
log_end_msg $? log_end_msg $?
rm -f "$PIDFILE" rm -f "$PIDFILE"
} }
# See how we were called.
case "$1" in case "$1" in
start) start)
start start
;; ;;
stop) stop)
stop stop
;; ;;
status) status)
status_of_proc -p "$PIDFILE" "$PROG" "$SHORTNAME" status_of_proc -p "$PIDFILE" "$PROG" "$SHORTNAME"
RETVAL=$? RETVAL=$?
;; ;;
restart) restart | force-reload)
stop stop
sleep 3 sleep 3
start start
;; ;;
*) *)
echo $"Usage: $whatami {start|stop|restart|status|help}" echo "Usage: $0 {start|stop|restart|force-reload|status}"
RETVAL=3 RETVAL=3
esac esac
exit $RETVAL exit $RETVAL

View File

@ -1,32 +0,0 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
description "Stop CloudStack VMs on shutdown"
author "Manuel Amador (Rudd-O) <manuel@vmops.com>"
start on stopping libvirt-bin
task
script
curr_runlevel=`runlevel | tail -c 2`
if [ "$curr_runlevel" = "6" -o "$curr_runlevel" = "0" ] ; then
for a in `virsh list | awk ' /^ +[0-9]+ [vri]-([0-9]+?)-/ { print $2 } '` ; do
echo Destroying CloudStack VM $a
virsh destroy $a
done
fi
end script

View File

@ -443,8 +443,6 @@ public class FakeComputingResource extends ServerResourceBase implements
String vmName = cmd.getVmName(); String vmName = cmd.getVmName();
Integer port = vmMgr.getVncPort(vmName); Integer port = vmMgr.getVncPort(vmName);
Long bytesReceived = null;
Long bytesSent = null;
State state = null; State state = null;
synchronized (_vms) { synchronized (_vms) {
@ -462,17 +460,16 @@ public class FakeComputingResource extends ServerResourceBase implements
s_logger.warn("Couldn't stop " + vmName); s_logger.warn("Couldn't stop " + vmName);
if (result != null) { if (result != null) {
return new StopAnswer(cmd, result); return new StopAnswer(cmd, result, false);
} }
} }
answer = new StopAnswer(cmd, null, port, bytesSent, bytesReceived); answer = new StopAnswer(cmd, null, port, true);
String result2 = vmMgr.cleanupVnet(cmd.getVnet()); String result2 = vmMgr.cleanupVnet(cmd.getVnet());
if (result2 != null) { if (result2 != null) {
result = result2 + (result != null ? ("\n" + result) : ""); result = result2 + (result != null ? ("\n" + result) : "");
answer = new StopAnswer(cmd, result, port, bytesSent, answer = new StopAnswer(cmd, result, port, true);
bytesReceived);
} }
_dhcpSnooper.cleanup(vmName, null); _dhcpSnooper.cleanup(vmName, null);
@ -498,7 +495,7 @@ public class FakeComputingResource extends ServerResourceBase implements
protected Answer execute(RebootCommand cmd) { protected Answer execute(RebootCommand cmd) {
VmMgr vmMgr = getVmManager(); VmMgr vmMgr = getVmManager();
vmMgr.rebootVM(cmd.getVmName()); vmMgr.rebootVM(cmd.getVmName());
return new RebootAnswer(cmd, "success", 0L, 0L); return new RebootAnswer(cmd, "success", true);
} }
private Answer execute(PingTestCommand cmd) { private Answer execute(PingTestCommand cmd) {

View File

@ -53,7 +53,7 @@ public class KVMHAChecker extends KVMHABase implements Callable<Boolean> {
cmd.add("-h", _hostIP); cmd.add("-h", _hostIP);
cmd.add("-r"); cmd.add("-r");
cmd.add("-t", cmd.add("-t",
String.valueOf((_heartBeatUpdateFreq + _heartBeatUpdateTimeout) / 1000 * 2)); String.valueOf(_heartBeatUpdateFreq/1000));
OutputInterpreter.OneLineParser parser = new OutputInterpreter.OneLineParser(); OutputInterpreter.OneLineParser parser = new OutputInterpreter.OneLineParser();
String result = cmd.execute(parser); String result = cmd.execute(parser);
s_logger.debug("pool: " + pool._poolIp); s_logger.debug("pool: " + pool._poolIp);

View File

@ -30,12 +30,15 @@ import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.text.DateFormat;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -154,6 +157,7 @@ import com.cloud.agent.resource.computing.KVMHABase.NfsStoragePool;
import com.cloud.agent.resource.computing.LibvirtVMDef.ConsoleDef; import com.cloud.agent.resource.computing.LibvirtVMDef.ConsoleDef;
import com.cloud.agent.resource.computing.LibvirtVMDef.DevicesDef; import com.cloud.agent.resource.computing.LibvirtVMDef.DevicesDef;
import com.cloud.agent.resource.computing.LibvirtVMDef.DiskDef; import com.cloud.agent.resource.computing.LibvirtVMDef.DiskDef;
import com.cloud.agent.resource.computing.LibvirtVMDef.DiskDef.diskProtocol;
import com.cloud.agent.resource.computing.LibvirtVMDef.FeaturesDef; import com.cloud.agent.resource.computing.LibvirtVMDef.FeaturesDef;
import com.cloud.agent.resource.computing.LibvirtVMDef.GraphicDef; import com.cloud.agent.resource.computing.LibvirtVMDef.GraphicDef;
import com.cloud.agent.resource.computing.LibvirtVMDef.GuestDef; import com.cloud.agent.resource.computing.LibvirtVMDef.GuestDef;
@ -1298,6 +1302,13 @@ public class LibvirtComputingResource extends ServerResourceBase implements
KVMStoragePool primaryPool = _storagePoolMgr.getStoragePool(cmd KVMStoragePool primaryPool = _storagePoolMgr.getStoragePool(cmd
.getPool().getUuid()); .getPool().getUuid());
if (primaryPool.getType() == StoragePoolType.RBD) {
s_logger.debug("Snapshots are not supported on RBD volumes");
return new ManageSnapshotAnswer(cmd, false,
"Snapshots are not supported on RBD volumes");
}
KVMPhysicalDisk disk = primaryPool.getPhysicalDisk(cmd KVMPhysicalDisk disk = primaryPool.getPhysicalDisk(cmd
.getVolumePath()); .getVolumePath());
if (state == DomainInfo.DomainState.VIR_DOMAIN_RUNNING if (state == DomainInfo.DomainState.VIR_DOMAIN_RUNNING
@ -1644,6 +1655,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements
+ templateInstallFolder; + templateInstallFolder;
_storage.mkdirs(tmpltPath); _storage.mkdirs(tmpltPath);
if (primary.getType() != StoragePoolType.RBD) {
Script command = new Script(_createTmplPath, _cmdsTimeout, s_logger); Script command = new Script(_createTmplPath, _cmdsTimeout, s_logger);
command.add("-f", disk.getPath()); command.add("-f", disk.getPath());
command.add("-t", tmpltPath); command.add("-t", tmpltPath);
@ -1655,6 +1667,32 @@ public class LibvirtComputingResource extends ServerResourceBase implements
s_logger.debug("failed to create template: " + result); s_logger.debug("failed to create template: " + result);
return new CreatePrivateTemplateAnswer(cmd, false, result); return new CreatePrivateTemplateAnswer(cmd, false, result);
} }
} else {
s_logger.debug("Converting RBD disk " + disk.getPath() + " into template " + cmd.getUniqueName());
Script.runSimpleBashScript("qemu-img convert"
+ " -f raw -O qcow2 "
+ KVMPhysicalDisk.RBDStringBuilder(primary.getSourceHost(),
primary.getSourcePort(),
primary.getAuthUserName(),
primary.getAuthSecret(),
disk.getPath())
+ " " + tmpltPath + "/" + cmd.getUniqueName() + ".qcow2");
File templateProp = new File(tmpltPath + "/template.properties");
if (!templateProp.exists()) {
templateProp.createNewFile();
}
String templateContent = "filename=" + cmd.getUniqueName() + ".qcow2" + System.getProperty("line.separator");
DateFormat dateFormat = new SimpleDateFormat("MM_dd_yyyy");
Date date = new Date();
templateContent += "snapshot.name=" + dateFormat.format(date) + System.getProperty("line.separator");
FileOutputStream templFo = new FileOutputStream(templateProp);
templFo.write(templateContent.getBytes());
templFo.flush();
templFo.close();
}
Map<String, Object> params = new HashMap<String, Object>(); Map<String, Object> params = new HashMap<String, Object>();
params.put(StorageLayer.InstanceConfigKey, _storage); params.put(StorageLayer.InstanceConfigKey, _storage);
@ -1756,8 +1794,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements
protected Answer execute(ModifyStoragePoolCommand cmd) { protected Answer execute(ModifyStoragePoolCommand cmd) {
KVMStoragePool storagepool = _storagePoolMgr.createStoragePool(cmd KVMStoragePool storagepool = _storagePoolMgr.createStoragePool(cmd
.getPool().getUuid(), cmd.getPool().getHost(), cmd.getPool() .getPool().getUuid(), cmd.getPool().getHost(), cmd.getPool().getPort(),
.getPath(), cmd.getPool().getType()); cmd.getPool().getPath(), cmd.getPool().getUserInfo(), cmd.getPool().getType());
if (storagepool == null) { if (storagepool == null) {
return new Answer(cmd, false, " Failed to create storage pool"); return new Answer(cmd, false, " Failed to create storage pool");
} }
@ -2234,8 +2272,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements
} }
private Answer execute(RebootCommand cmd) { private Answer execute(RebootCommand cmd) {
Long bytesReceived = null;
Long bytesSent = null;
synchronized (_vms) { synchronized (_vms) {
_vms.put(cmd.getVmName(), State.Starting); _vms.put(cmd.getVmName(), State.Starting);
@ -2252,13 +2288,12 @@ public class LibvirtComputingResource extends ServerResourceBase implements
} }
get_rule_logs_for_vms(); get_rule_logs_for_vms();
return new RebootAnswer(cmd, null, bytesSent, bytesReceived, return new RebootAnswer(cmd, null, vncPort);
vncPort);
} else { } else {
return new RebootAnswer(cmd, result); return new RebootAnswer(cmd, result, false);
} }
} catch (LibvirtException e) { } catch (LibvirtException e) {
return new RebootAnswer(cmd, e.getMessage()); return new RebootAnswer(cmd, e.getMessage(), false);
} finally { } finally {
synchronized (_vms) { synchronized (_vms) {
_vms.put(cmd.getVmName(), State.Running); _vms.put(cmd.getVmName(), State.Running);
@ -2267,16 +2302,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements
} }
protected Answer execute(RebootRouterCommand cmd) { protected Answer execute(RebootRouterCommand cmd) {
Long bytesSent = 0L;
Long bytesRcvd = 0L;
if (VirtualMachineName.isValidRouterName(cmd.getVmName())) {
long[] stats = getNetworkStats(cmd.getPrivateIpAddress());
bytesSent = stats[0];
bytesRcvd = stats[1];
}
RebootAnswer answer = (RebootAnswer) execute((RebootCommand) cmd); RebootAnswer answer = (RebootAnswer) execute((RebootCommand) cmd);
answer.setBytesSent(bytesSent);
answer.setBytesReceived(bytesRcvd);
String result = _virtRouterResource.connect(cmd.getPrivateIpAddress()); String result = _virtRouterResource.connect(cmd.getPrivateIpAddress());
if (result == null) { if (result == null) {
networkUsage(cmd.getPrivateIpAddress(), "create", null); networkUsage(cmd.getPrivateIpAddress(), "create", null);
@ -2309,9 +2335,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements
protected Answer execute(StopCommand cmd) { protected Answer execute(StopCommand cmd) {
final String vmName = cmd.getVmName(); final String vmName = cmd.getVmName();
Long bytesReceived = new Long(0);
Long bytesSent = new Long(0);
State state = null; State state = null;
synchronized (_vms) { synchronized (_vms) {
state = _vms.get(vmName); state = _vms.get(vmName);
@ -2337,9 +2360,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements
result = result2 + result; result = result2 + result;
} }
state = State.Stopped; state = State.Stopped;
return new StopAnswer(cmd, result, 0, bytesSent, bytesReceived); return new StopAnswer(cmd, result, 0, true);
} catch (LibvirtException e) { } catch (LibvirtException e) {
return new StopAnswer(cmd, e.getMessage()); return new StopAnswer(cmd, e.getMessage(), false);
} finally { } finally {
synchronized (_vms) { synchronized (_vms) {
if (state != null) { if (state != null) {
@ -2626,7 +2649,16 @@ public class LibvirtComputingResource extends ServerResourceBase implements
} else { } else {
int devId = (int) volume.getDeviceId(); int devId = (int) volume.getDeviceId();
if (volume.getType() == Volume.Type.DATADISK) { if (pool.getType() == StoragePoolType.RBD) {
/*
For RBD pools we use the secret mechanism in libvirt.
We store the secret under the UUID of the pool, that's why
we pass the pool's UUID as the authSecret
*/
disk.defNetworkBasedDisk(physicalDisk.getPath().replace("rbd:", ""), pool.getSourceHost(), pool.getSourcePort(),
pool.getAuthUserName(), pool.getUuid(),
devId, diskBusType, diskProtocol.RBD);
} else if (volume.getType() == Volume.Type.DATADISK) {
disk.defFileBasedDisk(physicalDisk.getPath(), devId, disk.defFileBasedDisk(physicalDisk.getPath(), devId,
DiskDef.diskBus.VIRTIO, DiskDef.diskBus.VIRTIO,
DiskDef.diskFmtType.QCOW2); DiskDef.diskFmtType.QCOW2);
@ -2984,8 +3016,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements
try { try {
KVMStoragePool localStoragePool = _storagePoolMgr KVMStoragePool localStoragePool = _storagePoolMgr
.createStoragePool(_localStorageUUID, "localhost", .createStoragePool(_localStorageUUID, "localhost", -1,
_localStoragePath, StoragePoolType.Filesystem); _localStoragePath, "", StoragePoolType.Filesystem);
com.cloud.agent.api.StoragePoolInfo pi = new com.cloud.agent.api.StoragePoolInfo( com.cloud.agent.api.StoragePoolInfo pi = new com.cloud.agent.api.StoragePoolInfo(
localStoragePool.getUuid(), cmd.getPrivateIpAddress(), localStoragePool.getUuid(), cmd.getPrivateIpAddress(),
_localStoragePath, _localStoragePath, _localStoragePath, _localStoragePath,
@ -4085,5 +4117,4 @@ public class LibvirtComputingResource extends ServerResourceBase implements
return new Answer(cmd, success, ""); return new Answer(cmd, success, "");
} }
} }

View File

@ -0,0 +1,106 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.agent.resource.computing;
public class LibvirtSecretDef {
public enum usage {
VOLUME("volume"), CEPH("ceph");
String _usage;
usage(String usage) {
_usage = usage;
}
@Override
public String toString() {
return _usage;
}
}
private usage _usage;
private boolean _ephemeral;
private boolean _private;
private String _uuid;
private String _description;
private String _cephName;
private String _volumeVolume;
public LibvirtSecretDef (usage usage, String uuid) {
_usage = usage;
_uuid = uuid;
}
public LibvirtSecretDef (usage usage, String uuid, String description) {
_usage = usage;
_uuid = uuid;
_description = description;
}
public boolean getEphemeral() {
return _ephemeral;
}
public boolean getPrivate() {
return _private;
}
public String getUuid() {
return _uuid;
}
public String getDescription() {
return _description;
}
public String getVolumeVolume() {
return _volumeVolume;
}
public String getCephName() {
return _cephName;
}
public void setVolumeVolume(String volume) {
_volumeVolume = volume;
}
public void setCephName(String name) {
_cephName = name;
}
@Override
public String toString() {
StringBuilder secretBuilder = new StringBuilder();
secretBuilder.append("<secret ephemeral='" + (_ephemeral ? "yes" : "no") + "' private='" + (_private ? "yes" : "no") + "'>\n");
secretBuilder.append("<uuid>" + _uuid + "</uuid>\n");
if (_description != null) {
secretBuilder.append("<description>" + _description + "</description>\n");
}
secretBuilder.append("<usage type='" + _usage + "'>\n");
if (_usage == _usage.VOLUME) {
secretBuilder.append("<volume>" + _volumeVolume + "</volume>\n");
}
if (_usage == _usage.CEPH) {
secretBuilder.append("<name>" + _cephName + "</name>\n");
}
secretBuilder.append("</usage>\n");
secretBuilder.append("</secret>\n");
return secretBuilder.toString();
}
}

View File

@ -18,7 +18,7 @@ package com.cloud.agent.resource.computing;
public class LibvirtStoragePoolDef { public class LibvirtStoragePoolDef {
public enum poolType { public enum poolType {
ISCSI("iscsi"), NETFS("netfs"), LOGICAL("logical"), DIR("dir"); ISCSI("iscsi"), NETFS("netfs"), LOGICAL("logical"), DIR("dir"), RBD("rbd");
String _poolType; String _poolType;
poolType(String poolType) { poolType(String poolType) {
@ -31,12 +31,41 @@ public class LibvirtStoragePoolDef {
} }
} }
public enum authType {
CHAP("chap"), CEPH("ceph");
String _authType;
authType(String authType) {
_authType = authType;
}
@Override
public String toString() {
return _authType;
}
}
private poolType _poolType; private poolType _poolType;
private String _poolName; private String _poolName;
private String _uuid; private String _uuid;
private String _sourceHost; private String _sourceHost;
private int _sourcePort;
private String _sourceDir; private String _sourceDir;
private String _targetPath; private String _targetPath;
private String _authUsername;
private authType _authType;
private String _secretUuid;
public LibvirtStoragePoolDef(poolType type, String poolName, String uuid,
String host, int port, String dir, String targetPath) {
_poolType = type;
_poolName = poolName;
_uuid = uuid;
_sourceHost = host;
_sourcePort = port;
_sourceDir = dir;
_targetPath = targetPath;
}
public LibvirtStoragePoolDef(poolType type, String poolName, String uuid, public LibvirtStoragePoolDef(poolType type, String poolName, String uuid,
String host, String dir, String targetPath) { String host, String dir, String targetPath) {
@ -48,6 +77,20 @@ public class LibvirtStoragePoolDef {
_targetPath = targetPath; _targetPath = targetPath;
} }
public LibvirtStoragePoolDef(poolType type, String poolName, String uuid,
String sourceHost, int sourcePort, String dir, String authUsername,
authType authType, String secretUuid) {
_poolType = type;
_poolName = poolName;
_uuid = uuid;
_sourceHost = sourceHost;
_sourcePort = sourcePort;
_sourceDir = dir;
_authUsername = authUsername;
_authType = authType;
_secretUuid = secretUuid;
}
public String getPoolName() { public String getPoolName() {
return _poolName; return _poolName;
} }
@ -60,6 +103,10 @@ public class LibvirtStoragePoolDef {
return _sourceHost; return _sourceHost;
} }
public int getSourcePort() {
return _sourcePort;
}
public String getSourceDir() { public String getSourceDir() {
return _sourceDir; return _sourceDir;
} }
@ -68,6 +115,18 @@ public class LibvirtStoragePoolDef {
return _targetPath; return _targetPath;
} }
public String getAuthUserName() {
return _authUsername;
}
public String getSecretUUID() {
return _secretUuid;
}
public authType getAuthType() {
return _authType;
}
@Override @Override
public String toString() { public String toString() {
StringBuilder storagePoolBuilder = new StringBuilder(); StringBuilder storagePoolBuilder = new StringBuilder();
@ -81,9 +140,22 @@ public class LibvirtStoragePoolDef {
storagePoolBuilder.append("<dir path='" + _sourceDir + "'/>\n"); storagePoolBuilder.append("<dir path='" + _sourceDir + "'/>\n");
storagePoolBuilder.append("</source>\n"); storagePoolBuilder.append("</source>\n");
} }
storagePoolBuilder.append("<target>\n"); if (_poolType == poolType.RBD) {
storagePoolBuilder.append("<path>" + _targetPath + "</path>\n"); storagePoolBuilder.append("<source>\n");
storagePoolBuilder.append("</target>\n"); storagePoolBuilder.append("<host name='" + _sourceHost + "' port='" + _sourcePort + "'/>\n");
storagePoolBuilder.append("<name>" + _sourceDir + "</name>\n");
if (_authUsername != null) {
storagePoolBuilder.append("<auth username='" + _authUsername + "' type='" + _authType + "'>\n");
storagePoolBuilder.append("<secret uuid='" + _secretUuid + "'/>\n");
storagePoolBuilder.append("</auth>\n");
}
storagePoolBuilder.append("</source>\n");
}
if (_poolType != poolType.RBD) {
storagePoolBuilder.append("<target>\n");
storagePoolBuilder.append("<path>" + _targetPath + "</path>\n");
storagePoolBuilder.append("</target>\n");
}
storagePoolBuilder.append("</pool>\n"); storagePoolBuilder.append("</pool>\n");
return storagePoolBuilder.toString(); return storagePoolBuilder.toString();
} }

View File

@ -51,15 +51,34 @@ public class LibvirtStoragePoolXMLParser {
Element source = (Element) rootElement.getElementsByTagName( Element source = (Element) rootElement.getElementsByTagName(
"source").item(0); "source").item(0);
String host = getAttrValue("host", "name", source); String host = getAttrValue("host", "name", source);
String path = getAttrValue("dir", "path", source);
Element target = (Element) rootElement.getElementsByTagName( if (type.equalsIgnoreCase("rbd")) {
"target").item(0); int port = Integer.parseInt(getAttrValue("host", "port", source));
String targetPath = getTagValue("path", target); String pool = getTagValue("name", source);
return new LibvirtStoragePoolDef( Element auth = (Element) source.getElementsByTagName(
LibvirtStoragePoolDef.poolType.valueOf(type.toUpperCase()), "auth").item(0);
poolName, uuid, host, path, targetPath);
if (auth != null) {
String authUsername = auth.getAttribute("username");
String authType = auth.getAttribute("type");
return new LibvirtStoragePoolDef(LibvirtStoragePoolDef.poolType.valueOf(type.toUpperCase()),
poolName, uuid, host, port, pool, authUsername, LibvirtStoragePoolDef.authType.valueOf(authType.toUpperCase()), uuid);
} else {
return new LibvirtStoragePoolDef(LibvirtStoragePoolDef.poolType.valueOf(type.toUpperCase()),
poolName, uuid, host, port, pool, "");
}
} else {
String path = getAttrValue("dir", "path", source);
Element target = (Element) rootElement.getElementsByTagName(
"target").item(0);
String targetPath = getTagValue("path", target);
return new LibvirtStoragePoolDef(
LibvirtStoragePoolDef.poolType.valueOf(type.toUpperCase()),
poolName, uuid, host, path, targetPath);
}
} catch (ParserConfigurationException e) { } catch (ParserConfigurationException e) {
s_logger.debug(e.toString()); s_logger.debug(e.toString());
} catch (SAXException e) { } catch (SAXException e) {

View File

@ -338,7 +338,7 @@ public class LibvirtVMDef {
} }
enum diskType { enum diskType {
FILE("file"), BLOCK("block"), DIRECTROY("dir"); FILE("file"), BLOCK("block"), DIRECTROY("dir"), NETWORK("network");
String _diskType; String _diskType;
diskType(String type) { diskType(String type) {
@ -351,6 +351,20 @@ public class LibvirtVMDef {
} }
} }
enum diskProtocol {
RBD("rbd"), SHEEPDOG("sheepdog");
String _diskProtocol;
diskProtocol(String protocol) {
_diskProtocol = protocol;
}
@Override
public String toString() {
return _diskProtocol;
}
}
enum diskBus { enum diskBus {
IDE("ide"), SCSI("scsi"), VIRTIO("virtio"), XEN("xen"), USB("usb"), UML( IDE("ide"), SCSI("scsi"), VIRTIO("virtio"), XEN("xen"), USB("usb"), UML(
"uml"), FDC("fdc"); "uml"), FDC("fdc");
@ -382,7 +396,12 @@ public class LibvirtVMDef {
private deviceType _deviceType; /* floppy, disk, cdrom */ private deviceType _deviceType; /* floppy, disk, cdrom */
private diskType _diskType; private diskType _diskType;
private diskProtocol _diskProtocol;
private String _sourcePath; private String _sourcePath;
private String _sourceHost;
private int _sourcePort;
private String _authUserName;
private String _authSecretUUID;
private String _diskLabel; private String _diskLabel;
private diskBus _bus; private diskBus _bus;
private diskFmtType _diskFmtType; /* qcow2, raw etc. */ private diskFmtType _diskFmtType; /* qcow2, raw etc. */
@ -461,6 +480,38 @@ public class LibvirtVMDef {
_bus = bus; _bus = bus;
} }
public void defNetworkBasedDisk(String diskName, String sourceHost, int sourcePort,
String authUserName, String authSecretUUID,
int devId, diskBus bus, diskProtocol protocol) {
_diskType = diskType.NETWORK;
_deviceType = deviceType.DISK;
_diskFmtType = diskFmtType.RAW;
_sourcePath = diskName;
_sourceHost = sourceHost;
_sourcePort = sourcePort;
_authUserName = authUserName;
_authSecretUUID = authSecretUUID;
_diskLabel = getDevLabel(devId, bus);
_bus = bus;
_diskProtocol = protocol;
}
public void defNetworkBasedDisk(String diskName, String sourceHost, int sourcePort,
String authUserName, String authSecretUUID,
String diskLabel, diskBus bus, diskProtocol protocol) {
_diskType = diskType.NETWORK;
_deviceType = deviceType.DISK;
_diskFmtType = diskFmtType.RAW;
_sourcePath = diskName;
_sourceHost = sourceHost;
_sourcePort = sourcePort;
_authUserName = authUserName;
_authSecretUUID = authSecretUUID;
_diskLabel = diskLabel;
_bus = bus;
_diskProtocol = protocol;
}
public void setReadonly() { public void setReadonly() {
_readonly = true; _readonly = true;
} }
@ -527,6 +578,18 @@ public class LibvirtVMDef {
diskBuilder.append(" dev='" + _sourcePath + "'"); diskBuilder.append(" dev='" + _sourcePath + "'");
} }
diskBuilder.append("/>\n"); diskBuilder.append("/>\n");
} else if (_diskType == diskType.NETWORK) {
diskBuilder.append("<source ");
diskBuilder.append(" protocol='" + _diskProtocol + "'");
diskBuilder.append(" name='" + _sourcePath + "'");
diskBuilder.append(">\n");
diskBuilder.append("<host name='" + _sourceHost + "' port='" + _sourcePort + "'/>\n");
diskBuilder.append("</source>\n");
if (_authUserName != null) {
diskBuilder.append("<auth username='" + _authUserName + "'>\n");
diskBuilder.append("<secret type='ceph' uuid='" + _authSecretUUID + "'/>\n");
diskBuilder.append("</auth>\n");
}
} }
diskBuilder.append("<target dev='" + _diskLabel + "'"); diskBuilder.append("<target dev='" + _diskLabel + "'");
if (_bus != null) { if (_bus != null) {
@ -898,5 +961,4 @@ public class LibvirtVMDef {
System.out.println(vm.toString()); System.out.println(vm.toString());
} }
} }

View File

@ -34,6 +34,22 @@ public class KVMPhysicalDisk {
} }
} }
public static String RBDStringBuilder(String monHost, int monPort,
String authUserName, String authSecret, String image) {
String rbdOpts;
rbdOpts = "rbd:" + image;
rbdOpts += ":mon_host=" + monHost + "\\\\:" + monPort;
if (authUserName == null) {
rbdOpts += ":auth_supported=none";
} else {
rbdOpts += ":auth_supported=cephx";
rbdOpts += ":id=" + authUserName;
rbdOpts += ":key=" + authSecret;
}
return rbdOpts;
}
private PhysicalDiskFormat format; private PhysicalDiskFormat format;
private long size; private long size;
private long virtualSize; private long virtualSize;

View File

@ -45,6 +45,16 @@ public interface KVMStoragePool {
public String getLocalPath(); public String getLocalPath();
public String getSourceHost();
public String getSourceDir();
public int getSourcePort();
public String getAuthUserName();
public String getAuthSecret();
public StoragePoolType getType(); public StoragePoolType getType();
public boolean delete(); public boolean delete();

View File

@ -52,10 +52,10 @@ public class KVMStoragePoolManager {
return this._storageAdaptor.getStoragePoolByUri(uri); return this._storageAdaptor.getStoragePoolByUri(uri);
} }
public KVMStoragePool createStoragePool(String name, String host, public KVMStoragePool createStoragePool(String name, String host, int port, String path,
String path, StoragePoolType type) { String userInfo, StoragePoolType type) {
KVMStoragePool pool = this._storageAdaptor.createStoragePool(name, KVMStoragePool pool = this._storageAdaptor.createStoragePool(name,
host, path, type); host, port, path, userInfo, type);
if (type == StoragePoolType.NetworkFilesystem) { if (type == StoragePoolType.NetworkFilesystem) {
KVMHABase.NfsStoragePool nfspool = new KVMHABase.NfsStoragePool( KVMHABase.NfsStoragePool nfspool = new KVMHABase.NfsStoragePool(
pool.getUuid(), host, path, pool.getLocalPath(), pool.getUuid(), host, path, pool.getLocalPath(),
@ -73,11 +73,16 @@ public class KVMStoragePoolManager {
return true; return true;
} }
public KVMPhysicalDisk createDiskFromTemplate(KVMPhysicalDisk template, public KVMPhysicalDisk createDiskFromTemplate(KVMPhysicalDisk template, String name,
String name, KVMStoragePool destPool) { KVMStoragePool destPool) {
return this._storageAdaptor.createDiskFromTemplate(template, name, if (destPool.getType() == StoragePoolType.RBD) {
KVMPhysicalDisk.PhysicalDiskFormat.QCOW2, return this._storageAdaptor.createDiskFromTemplate(template, name,
template.getSize(), destPool); KVMPhysicalDisk.PhysicalDiskFormat.RAW, template.getSize(), destPool);
} else {
return this._storageAdaptor.createDiskFromTemplate(template, name,
KVMPhysicalDisk.PhysicalDiskFormat.QCOW2,
template.getSize(), destPool);
}
} }
public KVMPhysicalDisk createTemplateFromDisk(KVMPhysicalDisk disk, public KVMPhysicalDisk createTemplateFromDisk(KVMPhysicalDisk disk,

View File

@ -23,8 +23,10 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.apache.commons.codec.binary.Base64;
import org.libvirt.Connect; import org.libvirt.Connect;
import org.libvirt.LibvirtException; import org.libvirt.LibvirtException;
import org.libvirt.Secret;
import org.libvirt.StoragePool; import org.libvirt.StoragePool;
import org.libvirt.StoragePoolInfo; import org.libvirt.StoragePoolInfo;
import org.libvirt.StorageVol; import org.libvirt.StorageVol;
@ -32,10 +34,13 @@ import org.libvirt.StoragePoolInfo.StoragePoolState;
import com.cloud.agent.api.ManageSnapshotCommand; import com.cloud.agent.api.ManageSnapshotCommand;
import com.cloud.agent.resource.computing.LibvirtConnection; import com.cloud.agent.resource.computing.LibvirtConnection;
import com.cloud.agent.resource.computing.LibvirtSecretDef;
import com.cloud.agent.resource.computing.LibvirtSecretDef.usage;
import com.cloud.agent.resource.computing.LibvirtStoragePoolDef; import com.cloud.agent.resource.computing.LibvirtStoragePoolDef;
import com.cloud.agent.resource.computing.LibvirtStoragePoolXMLParser; import com.cloud.agent.resource.computing.LibvirtStoragePoolXMLParser;
import com.cloud.agent.resource.computing.LibvirtStorageVolumeDef; import com.cloud.agent.resource.computing.LibvirtStorageVolumeDef;
import com.cloud.agent.resource.computing.LibvirtStoragePoolDef.poolType; import com.cloud.agent.resource.computing.LibvirtStoragePoolDef.poolType;
import com.cloud.agent.resource.computing.LibvirtStoragePoolDef.authType;
import com.cloud.agent.resource.computing.LibvirtStorageVolumeDef.volFormat; import com.cloud.agent.resource.computing.LibvirtStorageVolumeDef.volFormat;
import com.cloud.agent.resource.computing.LibvirtStorageVolumeXMLParser; import com.cloud.agent.resource.computing.LibvirtStorageVolumeXMLParser;
import com.cloud.agent.storage.KVMPhysicalDisk.PhysicalDiskFormat; import com.cloud.agent.storage.KVMPhysicalDisk.PhysicalDiskFormat;
@ -143,7 +148,6 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
synchronized (getStoragePool(uuid)) { synchronized (getStoragePool(uuid)) {
sp = conn.storagePoolDefineXML(spd.toString(), 0); sp = conn.storagePoolDefineXML(spd.toString(), 0);
if (sp == null) { if (sp == null) {
s_logger.debug("Failed to define storage pool"); s_logger.debug("Failed to define storage pool");
return null; return null;
@ -270,6 +274,60 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
} }
private StoragePool createRBDStoragePool(Connect conn, String uuid,
String host, int port, String userInfo, String path) {
LibvirtStoragePoolDef spd;
StoragePool sp = null;
String[] userInfoTemp = userInfo.split(":");
if (userInfoTemp.length == 2) {
s_logger.debug("libvirt secret information found. id: " + userInfoTemp[0] + " secret: " + userInfoTemp[1]);
LibvirtSecretDef sd = new LibvirtSecretDef(usage.CEPH, uuid);
Secret s = null;
sd.setCephName(userInfoTemp[0]);
try {
s_logger.debug(sd.toString());
s = conn.secretDefineXML(sd.toString());
s.setValue(Base64.decodeBase64(userInfoTemp[1]));
} catch (LibvirtException e) {
s_logger.debug(e.toString());
if (s != null) {
try {
s.undefine();
s.free();
} catch (LibvirtException l) {
s_logger.debug("Failed to define secret with: " + l.toString());
}
}
}
spd = new LibvirtStoragePoolDef(poolType.RBD, uuid, uuid, host, port, path, userInfoTemp[0], authType.CEPH, uuid);
} else {
spd = new LibvirtStoragePoolDef(poolType.RBD, uuid, uuid, host, port, path, "");
}
try {
s_logger.debug(spd.toString());
sp = conn.storagePoolDefineXML(spd.toString(), 0);
sp.create(0);
return sp;
} catch (LibvirtException e) {
s_logger.debug(e.toString());
if (sp != null) {
try {
sp.undefine();
sp.free();
} catch (LibvirtException l) {
s_logger.debug("Failed to define RBD storage pool with: " + l.toString());
}
}
return null;
}
}
public StorageVol copyVolume(StoragePool destPool, public StorageVol copyVolume(StoragePool destPool,
LibvirtStorageVolumeDef destVol, StorageVol srcVol, int timeout) LibvirtStorageVolumeDef destVol, StorageVol srcVol, int timeout)
throws LibvirtException { throws LibvirtException {
@ -422,11 +480,36 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
if (spd.getPoolType() == LibvirtStoragePoolDef.poolType.NETFS if (spd.getPoolType() == LibvirtStoragePoolDef.poolType.NETFS
|| spd.getPoolType() == LibvirtStoragePoolDef.poolType.DIR) { || spd.getPoolType() == LibvirtStoragePoolDef.poolType.DIR) {
type = StoragePoolType.Filesystem; type = StoragePoolType.Filesystem;
} else if (spd.getPoolType() == LibvirtStoragePoolDef.poolType.RBD) {
type = StoragePoolType.RBD;
} }
LibvirtStoragePool pool = new LibvirtStoragePool(uuid,
storage.getName(), type, this, storage); LibvirtStoragePool pool = new LibvirtStoragePool(uuid, storage.getName(),
pool.setLocalPath(spd.getTargetPath()); type, this, storage);
getStats(pool);
if (pool.getType() != StoragePoolType.RBD) {
pool.setLocalPath(spd.getTargetPath());
} else {
pool.setLocalPath("");
pool.setSourceHost(spd.getSourceHost());
pool.setSourcePort(spd.getSourcePort());
pool.setSourceDir(spd.getSourceDir());
String authUsername = spd.getAuthUserName();
if (authUsername != null) {
Secret secret = conn.secretLookupByUUIDString(spd.getSecretUUID());
String secretValue = new String(Base64.encodeBase64(secret.getByteValue()));
pool.setAuthUsername(authUsername);
pool.setAuthSecret(secretValue);
}
}
if (pool.getType() == StoragePoolType.RBD) {
pool.setCapacity(storage.getInfo().capacity);
pool.setUsed(storage.getInfo().allocation);
} else {
getStats(pool);
}
return pool; return pool;
} catch (LibvirtException e) { } catch (LibvirtException e) {
throw new CloudRuntimeException(e.toString()); throw new CloudRuntimeException(e.toString());
@ -448,6 +531,8 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
disk.setVirtualSize(vol.getInfo().capacity); disk.setVirtualSize(vol.getInfo().capacity);
if (voldef.getFormat() == null) { if (voldef.getFormat() == null) {
disk.setFormat(pool.getDefaultFormat()); disk.setFormat(pool.getDefaultFormat());
} else if (pool.getType() == StoragePoolType.RBD) {
disk.setFormat(KVMPhysicalDisk.PhysicalDiskFormat.RAW);
} else if (voldef.getFormat() == LibvirtStorageVolumeDef.volFormat.QCOW2) { } else if (voldef.getFormat() == LibvirtStorageVolumeDef.volFormat.QCOW2) {
disk.setFormat(KVMPhysicalDisk.PhysicalDiskFormat.QCOW2); disk.setFormat(KVMPhysicalDisk.PhysicalDiskFormat.QCOW2);
} else if (voldef.getFormat() == LibvirtStorageVolumeDef.volFormat.RAW) { } else if (voldef.getFormat() == LibvirtStorageVolumeDef.volFormat.RAW) {
@ -461,8 +546,8 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
} }
@Override @Override
public KVMStoragePool createStoragePool(String name, String host, public KVMStoragePool createStoragePool(String name, String host, int port,
String path, StoragePoolType type) { String path, String userInfo, StoragePoolType type) {
StoragePool sp = null; StoragePool sp = null;
Connect conn = null; Connect conn = null;
try { try {
@ -487,6 +572,8 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
} else if (type == StoragePoolType.SharedMountPoint } else if (type == StoragePoolType.SharedMountPoint
|| type == StoragePoolType.Filesystem) { || type == StoragePoolType.Filesystem) {
sp = CreateSharedStoragePool(conn, name, host, path); sp = CreateSharedStoragePool(conn, name, host, path);
} else if (type == StoragePoolType.RBD) {
sp = createRBDStoragePool(conn, name, host, port, userInfo, path);
} }
} }
@ -499,15 +586,23 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
LibvirtStoragePoolDef spd = getStoragePoolDef(conn, sp); LibvirtStoragePoolDef spd = getStoragePoolDef(conn, sp);
LibvirtStoragePool pool = new LibvirtStoragePool(name, LibvirtStoragePool pool = new LibvirtStoragePool(name,
sp.getName(), type, this, sp); sp.getName(), type, this, sp);
pool.setLocalPath(spd.getTargetPath());
getStats(pool); if (pool.getType() != StoragePoolType.RBD) {
pool.setLocalPath(spd.getTargetPath());
} else {
pool.setLocalPath("");
}
if (pool.getType() == StoragePoolType.RBD) {
pool.setCapacity(sp.getInfo().capacity);
pool.setUsed(sp.getInfo().allocation);
} else {
getStats(pool);
}
return pool; return pool;
} catch (LibvirtException e) { } catch (LibvirtException e) {
throw new CloudRuntimeException(e.toString()); throw new CloudRuntimeException(e.toString());
} }
} }
@Override @Override
@ -520,6 +615,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
} }
StoragePool sp = null; StoragePool sp = null;
Secret s = null;
try { try {
sp = conn.storagePoolLookupByUUIDString(uuid); sp = conn.storagePoolLookupByUUIDString(uuid);
@ -527,10 +623,23 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
return true; return true;
} }
/*
* Some storage pools, like RBD also have 'secret' information stored in libvirt
* Destroy them if they exist
*/
try {
s = conn.secretLookupByUUIDString(uuid);
} catch (LibvirtException e) {
}
try { try {
sp.destroy(); sp.destroy();
sp.undefine(); sp.undefine();
sp.free(); sp.free();
if (s != null) {
s.undefine();
s.free();
}
return true; return true;
} catch (LibvirtException e) { } catch (LibvirtException e) {
throw new CloudRuntimeException(e.toString()); throw new CloudRuntimeException(e.toString());
@ -543,6 +652,11 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
LibvirtStoragePool libvirtPool = (LibvirtStoragePool) pool; LibvirtStoragePool libvirtPool = (LibvirtStoragePool) pool;
StoragePool virtPool = libvirtPool.getPool(); StoragePool virtPool = libvirtPool.getPool();
LibvirtStorageVolumeDef.volFormat libvirtformat = null; LibvirtStorageVolumeDef.volFormat libvirtformat = null;
if (pool.getType() == StoragePoolType.RBD) {
format = PhysicalDiskFormat.RAW;
}
if (format == PhysicalDiskFormat.QCOW2) { if (format == PhysicalDiskFormat.QCOW2) {
libvirtformat = LibvirtStorageVolumeDef.volFormat.QCOW2; libvirtformat = LibvirtStorageVolumeDef.volFormat.QCOW2;
} else if (format == PhysicalDiskFormat.RAW) { } else if (format == PhysicalDiskFormat.RAW) {
@ -580,19 +694,58 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
@Override @Override
public KVMPhysicalDisk createDiskFromTemplate(KVMPhysicalDisk template, public KVMPhysicalDisk createDiskFromTemplate(KVMPhysicalDisk template,
String name, PhysicalDiskFormat format, long size, String name, PhysicalDiskFormat format, long size, KVMStoragePool destPool) {
KVMStoragePool destPool) {
KVMPhysicalDisk disk = destPool.createPhysicalDisk(UUID.randomUUID() String newUuid = UUID.randomUUID().toString();
.toString(), format, template.getVirtualSize()); KVMStoragePool srcPool = template.getPool();
KVMPhysicalDisk disk = null;
/*
With RBD you can't run qemu-img convert with an existing RBD image as destination
qemu-img will exit with the error that the destination already exists.
So for RBD we don't create the image, but let qemu-img do that for us.
We then create a KVMPhysicalDisk object that we can return
*/
if (destPool.getType() != StoragePoolType.RBD) {
disk = destPool.createPhysicalDisk(newUuid, format, template.getVirtualSize());
if (format == PhysicalDiskFormat.QCOW2) {
Script.runSimpleBashScript("qemu-img create -f " Script.runSimpleBashScript("qemu-img create -f "
+ template.getFormat() + " -b " + template.getPath() + " " + template.getFormat() + " -b " + template.getPath() + " "
+ disk.getPath()); + disk.getPath());
} else if (format == PhysicalDiskFormat.RAW) { } else {
Script.runSimpleBashScript("qemu-img convert -f " disk = new KVMPhysicalDisk(destPool.getSourceDir() + "/" + newUuid, newUuid, destPool);
+ template.getFormat() + " -O raw " + template.getPath() disk.setFormat(format);
+ " " + disk.getPath()); disk.setSize(template.getVirtualSize());
disk.setVirtualSize(disk.getSize());
if (srcPool.getType() != StoragePoolType.RBD) {
Script.runSimpleBashScript("qemu-img convert"
+ " -f " + template.getFormat()
+ " -O " + format
+ " " + template.getPath()
+ " " + KVMPhysicalDisk.RBDStringBuilder(destPool.getSourceHost(),
destPool.getSourcePort(),
destPool.getAuthUserName(),
destPool.getAuthSecret(),
disk.getPath()));
} else {
template.setFormat(PhysicalDiskFormat.RAW);
Script.runSimpleBashScript("qemu-img convert"
+ " -f " + template.getFormat()
+ " -O " + format
+ " " + KVMPhysicalDisk.RBDStringBuilder(srcPool.getSourceHost(),
srcPool.getSourcePort(),
srcPool.getAuthUserName(),
srcPool.getAuthSecret(),
template.getPath())
+ " " + KVMPhysicalDisk.RBDStringBuilder(destPool.getSourceHost(),
destPool.getSourcePort(),
destPool.getAuthUserName(),
destPool.getAuthSecret(),
disk.getPath()));
}
} }
return disk; return disk;
} }
@ -625,14 +778,60 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
@Override @Override
public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name, public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name,
KVMStoragePool destPool) { KVMStoragePool destPool) {
KVMPhysicalDisk newDisk = destPool.createPhysicalDisk(name,
disk.getVirtualSize());
String sourcePath = disk.getPath();
String destPath = newDisk.getPath();
Script.runSimpleBashScript("qemu-img convert -f " + disk.getFormat() /*
+ " -O " + newDisk.getFormat() + " " + sourcePath + " " With RBD you can't run qemu-img convert with an existing RBD image as destination
+ destPath); qemu-img will exit with the error that the destination already exists.
So for RBD we don't create the image, but let qemu-img do that for us.
We then create a KVMPhysicalDisk object that we can return
*/
KVMPhysicalDisk newDisk;
if (destPool.getType() != StoragePoolType.RBD) {
newDisk = destPool.createPhysicalDisk(name, disk.getVirtualSize());
} else {
newDisk = new KVMPhysicalDisk(destPool.getSourceDir() + "/" + name, name, destPool);
newDisk.setFormat(PhysicalDiskFormat.RAW);
newDisk.setSize(disk.getVirtualSize());
newDisk.setVirtualSize(disk.getSize());
}
KVMStoragePool srcPool = disk.getPool();
String destPath = newDisk.getPath();
String sourcePath = disk.getPath();
PhysicalDiskFormat sourceFormat = disk.getFormat();
PhysicalDiskFormat destFormat = newDisk.getFormat();
if ((srcPool.getType() != StoragePoolType.RBD) && (destPool.getType() != StoragePoolType.RBD)) {
Script.runSimpleBashScript("qemu-img convert -f " + sourceFormat
+ " -O " + destFormat
+ " " + sourcePath
+ " " + destPath);
} else if ((srcPool.getType() != StoragePoolType.RBD) && (destPool.getType() == StoragePoolType.RBD)) {
Script.runSimpleBashScript("qemu-img convert -f " + sourceFormat
+ " -O " + destFormat
+ " " + sourcePath
+ " " + KVMPhysicalDisk.RBDStringBuilder(destPool.getSourceHost(),
destPool.getSourcePort(),
destPool.getAuthUserName(),
destPool.getAuthSecret(),
destPath));
} else {
Script.runSimpleBashScript("qemu-img convert -f " + sourceFormat
+ " -O " + destFormat
+ " " + KVMPhysicalDisk.RBDStringBuilder(srcPool.getSourceHost(),
srcPool.getSourcePort(),
srcPool.getAuthUserName(),
srcPool.getAuthSecret(),
sourcePath)
+ " " + KVMPhysicalDisk.RBDStringBuilder(destPool.getSourceHost(),
destPool.getSourcePort(),
destPool.getAuthUserName(),
destPool.getAuthSecret(),
destPath));
}
return newDisk; return newDisk;
} }
@ -658,7 +857,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
protocal = StoragePoolType.NetworkFilesystem; protocal = StoragePoolType.NetworkFilesystem;
} }
return createStoragePool(uuid, sourceHost, sourcePath, protocal); return createStoragePool(uuid, sourceHost, 0, sourcePath, "", protocal);
} }
@Override @Override
@ -699,5 +898,4 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
return true; return true;
} }
} }

View File

@ -34,6 +34,11 @@ public class LibvirtStoragePool implements KVMStoragePool {
protected StoragePoolType type; protected StoragePoolType type;
protected StorageAdaptor _storageAdaptor; protected StorageAdaptor _storageAdaptor;
protected StoragePool _pool; protected StoragePool _pool;
protected String authUsername;
protected String authSecret;
protected String sourceHost;
protected int sourcePort;
protected String sourceDir;
public LibvirtStoragePool(String uuid, String name, StoragePoolType type, public LibvirtStoragePool(String uuid, String name, StoragePoolType type,
StorageAdaptor adaptor, StoragePool pool) { StorageAdaptor adaptor, StoragePool pool) {
@ -137,6 +142,51 @@ public class LibvirtStoragePool implements KVMStoragePool {
this.localPath = localPath; this.localPath = localPath;
} }
@Override
public String getAuthUserName() {
return this.authUsername;
}
public void setAuthUsername(String authUsername) {
this.authUsername = authUsername;
}
@Override
public String getAuthSecret() {
return this.authSecret;
}
public void setAuthSecret(String authSecret) {
this.authSecret = authSecret;
}
@Override
public String getSourceHost() {
return this.sourceHost;
}
public void setSourceHost(String host) {
this.sourceHost = host;
}
@Override
public int getSourcePort() {
return this.sourcePort;
}
public void setSourcePort(int port) {
this.sourcePort = port;
}
@Override
public String getSourceDir() {
return this.sourceDir;
}
public void setSourceDir(String dir) {
this.sourceDir = dir;
}
@Override @Override
public StoragePoolType getType() { public StoragePoolType getType() {
return this.type; return this.type;

View File

@ -30,8 +30,8 @@ public interface StorageAdaptor {
public KVMPhysicalDisk getPhysicalDisk(String volumeUuid, public KVMPhysicalDisk getPhysicalDisk(String volumeUuid,
KVMStoragePool pool); KVMStoragePool pool);
public KVMStoragePool createStoragePool(String name, String host, public KVMStoragePool createStoragePool(String name, String host, int port,
String path, StoragePoolType type); String path, String userInfo, StoragePoolType type);
public boolean deleteStoragePool(String uuid); public boolean deleteStoragePool(String uuid);

View File

@ -17,52 +17,25 @@
package com.cloud.agent.api; package com.cloud.agent.api;
public class RebootAnswer extends Answer { public class RebootAnswer extends Answer {
Long bytesSent;
Long bytesReceived;
Integer vncPort; Integer vncPort;
protected RebootAnswer() { protected RebootAnswer() {
} }
public RebootAnswer(RebootCommand cmd, String details, Long bytesSent, Long bytesReceived, Integer vncport) { public RebootAnswer(RebootCommand cmd, String details, Integer vncport) {
super(cmd, true, details); super(cmd, true, details);
this.bytesReceived = bytesReceived;
this.bytesSent = bytesSent;
this.vncPort = vncport; this.vncPort = vncport;
} }
public RebootAnswer(RebootCommand cmd, String details, Long bytesSent, Long bytesReceived) { public RebootAnswer(RebootCommand cmd, String details, boolean success) {
super(cmd, true, details); super(cmd, success, details);
this.bytesReceived = bytesReceived;
this.bytesSent = bytesSent;
this.vncPort = null; this.vncPort = null;
} }
public RebootAnswer(RebootCommand cmd, String details) {
super(cmd, false, details);
bytesSent = null;
bytesReceived = null;
}
public RebootAnswer(RebootCommand cmd, Exception e) { public RebootAnswer(RebootCommand cmd, Exception e) {
super(cmd, e); super(cmd, e);
} }
public void setBytesReceived(Long bytesReceived) {
this.bytesReceived = bytesReceived;
}
public Long getBytesReceived() {
return bytesReceived;
}
public void setBytesSent(Long bytesSent) {
this.bytesSent = bytesSent;
}
public Long getBytesSent() {
return bytesSent;
}
public Integer getVncPort() { public Integer getVncPort() {
return vncPort; return vncPort;
} }

View File

@ -22,13 +22,13 @@ public class StopAnswer extends RebootAnswer {
protected StopAnswer() { protected StopAnswer() {
} }
public StopAnswer(StopCommand cmd, String details, Integer vncPort, Long bytesSent, Long bytesReceived) { public StopAnswer(StopCommand cmd, String details, Integer vncPort, boolean success) {
super(cmd, details, bytesSent, bytesReceived); super(cmd, details, success);
this.vncPort = vncPort; this.vncPort = vncPort;
} }
public StopAnswer(StopCommand cmd, String details) { public StopAnswer(StopCommand cmd, String details, boolean success) {
super(cmd, details); super(cmd, details, success);
vncPort = null; vncPort = null;
} }

View File

@ -23,7 +23,6 @@ public class StopCommand extends RebootCommand {
private boolean isProxy=false; private boolean isProxy=false;
private String urlPort=null; private String urlPort=null;
private String publicConsoleProxyIpAddress=null; private String publicConsoleProxyIpAddress=null;
private String privateRouterIpAddress=null;
protected StopCommand() { protected StopCommand() {
} }
@ -45,12 +44,6 @@ public class StopCommand extends RebootCommand {
this.vnet = vnet; this.vnet = vnet;
} }
public StopCommand(VirtualMachine vm, String vmName, String vnet, String privateRouterIpAddress) {
super(vmName);
this.vnet = vnet;
this.privateRouterIpAddress = privateRouterIpAddress;
}
public StopCommand(String vmName) { public StopCommand(String vmName) {
super(vmName); super(vmName);
} }
@ -76,7 +69,4 @@ public class StopCommand extends RebootCommand {
return this.publicConsoleProxyIpAddress; return this.publicConsoleProxyIpAddress;
} }
public String getPrivateRouterIpAddress() {
return privateRouterIpAddress;
}
} }

View File

@ -24,6 +24,7 @@ public class StorageFilerTO {
String uuid; String uuid;
String host; String host;
String path; String path;
String userInfo;
int port; int port;
StoragePoolType type; StoragePoolType type;
@ -34,6 +35,7 @@ public class StorageFilerTO {
this.path = pool.getPath(); this.path = pool.getPath();
this.type = pool.getPoolType(); this.type = pool.getPoolType();
this.uuid = pool.getUuid(); this.uuid = pool.getUuid();
this.userInfo = pool.getUserInfo();
} }
public long getId() { public long getId() {
@ -52,6 +54,10 @@ public class StorageFilerTO {
return path; return path;
} }
public String getUserInfo() {
return userInfo;
}
public int getPort() { public int getPort() {
return port; return port;
} }

View File

@ -52,7 +52,7 @@ public class CreateFirewallRuleCmd extends BaseAsyncCreateCmd implements Firewal
// /////////////////////////////////////////////////// // ///////////////////////////////////////////////////
@IdentityMapper(entityTableName="user_ip_address") @IdentityMapper(entityTableName="user_ip_address")
@Parameter(name = ApiConstants.IP_ADDRESS_ID, type = CommandType.LONG, description = "the IP address id of the port forwarding rule") @Parameter(name = ApiConstants.IP_ADDRESS_ID, type = CommandType.LONG, required=true, description = "the IP address id of the port forwarding rule")
private Long ipAddressId; private Long ipAddressId;
@Parameter(name = ApiConstants.PROTOCOL, type = CommandType.STRING, required = true, description = "the protocol for the firewall rule. Valid values are TCP/UDP/ICMP.") @Parameter(name = ApiConstants.PROTOCOL, type = CommandType.STRING, required = true, description = "the protocol for the firewall rule. Valid values are TCP/UDP/ICMP.")

View File

@ -96,6 +96,7 @@ public class Storage {
Iscsi(true), // for e.g., ZFS Comstar Iscsi(true), // for e.g., ZFS Comstar
ISO(false), // for iso image ISO(false), // for iso image
LVM(false), // XenServer local LVM SR LVM(false), // XenServer local LVM SR
RBD(true),
SharedMountPoint(true), SharedMountPoint(true),
VMFS(true), // VMware VMFS storage VMFS(true), // VMware VMFS storage
PreSetup(true), // for XenServer, Storage Pool is set up by customers. PreSetup(true), // for XenServer, Storage Pool is set up by customers.

View File

@ -85,6 +85,11 @@ public interface StoragePool {
*/ */
String getPath(); String getPath();
/**
* @return the user information / credentials for the storage host
*/
String getUserInfo();
/** /**
* @return the storage pool represents a shared storage resource * @return the storage pool represents a shared storage resource
*/ */

View File

@ -169,7 +169,7 @@
<pluggableservice name="F5ExternalLoadBalancerElementService" key="com.cloud.network.element.F5ExternalLoadBalancerElementService" class="com.cloud.network.element.F5ExternalLoadBalancerElement"/> <pluggableservice name="F5ExternalLoadBalancerElementService" key="com.cloud.network.element.F5ExternalLoadBalancerElementService" class="com.cloud.network.element.F5ExternalLoadBalancerElement"/>
<pluggableservice name="JuniperSRXFirewallElementService" key="com.cloud.network.element.JuniperSRXFirewallElementService" class="com.cloud.network.element.JuniperSRXExternalFirewallElement"/> <pluggableservice name="JuniperSRXFirewallElementService" key="com.cloud.network.element.JuniperSRXFirewallElementService" class="com.cloud.network.element.JuniperSRXExternalFirewallElement"/>
<pluggableservice name="CiscoNexusVSMElementService" key="com.cloud.network.element.CiscoNexusVSMElementService" class="com.cloud.network.element.CiscoNexusVSMElement"/> <pluggableservice name="CiscoNexusVSMElementService" key="com.cloud.network.element.CiscoNexusVSMElementService" class="com.cloud.network.element.CiscoNexusVSMElement"/>
<pluggableservice name="NiciraNvpElementService" key="com.coud.network.element.NiciraNvpElementService" class="com.cloud.network.element.NiciraNvpElement"/> <pluggableservice name="NiciraNvpElementService" key="com.cloud.network.element.NiciraNvpElementService" class="com.cloud.network.element.NiciraNvpElement"/>
<dao name="NetScalerPodDao" class="com.cloud.network.dao.NetScalerPodDaoImpl" singleton="false"/> <dao name="NetScalerPodDao" class="com.cloud.network.dao.NetScalerPodDaoImpl" singleton="false"/>
<dao name="CiscoNexusVSMDeviceDao" class="com.cloud.network.dao.CiscoNexusVSMDeviceDaoImpl" singleton="false"/> <dao name="CiscoNexusVSMDeviceDao" class="com.cloud.network.dao.CiscoNexusVSMDeviceDaoImpl" singleton="false"/>
<dao name="OvsTunnelInterfaceDao" class="com.cloud.network.ovs.dao.OvsTunnelInterfaceDaoImpl" singleton="false"/> <dao name="OvsTunnelInterfaceDao" class="com.cloud.network.ovs.dao.OvsTunnelInterfaceDaoImpl" singleton="false"/>

View File

@ -1,19 +1,3 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
/* /*
* The contents of this file are subject to the "END USER LICENSE AGREEMENT FOR F5 * The contents of this file are subject to the "END USER LICENSE AGREEMENT FOR F5
* Software Development Kit for iControl"; you may not use this file except in * Software Development Kit for iControl"; you may not use this file except in

View File

@ -157,6 +157,9 @@ public class StoragePoolVO implements StoragePool, Identity {
@Column(name="port") @Column(name="port")
private int port; private int port;
@Column(name="user_info")
private String userInfo;
@Column(name="cluster_id") @Column(name="cluster_id")
private Long clusterId; private Long clusterId;
@ -179,6 +182,11 @@ public class StoragePoolVO implements StoragePool, Identity {
public String getPath() { public String getPath() {
return path; return path;
} }
@Override
public String getUserInfo() {
return userInfo;
}
public StoragePoolVO(long poolId, String name, String uuid, StoragePoolType type, public StoragePoolVO(long poolId, String name, String uuid, StoragePoolType type,
long dataCenterId, Long podId, long availableBytes, long capacityBytes, String hostAddress, int port, String hostPath) { long dataCenterId, Long podId, long availableBytes, long capacityBytes, String hostAddress, int port, String hostPath) {
@ -208,6 +216,16 @@ public class StoragePoolVO implements StoragePool, Identity {
this.setStatus(StoragePoolStatus.Up); this.setStatus(StoragePoolStatus.Up);
this.uuid = UUID.randomUUID().toString(); this.uuid = UUID.randomUUID().toString();
} }
public StoragePoolVO(StoragePoolType type, String hostAddress, int port, String path, String userInfo) {
this.poolType = type;
this.hostAddress = hostAddress;
this.port = port;
this.path = path;
this.userInfo = userInfo;
this.setStatus(StoragePoolStatus.Up);
this.uuid = UUID.randomUUID().toString();
}
public void setStatus(StoragePoolStatus status) public void setStatus(StoragePoolStatus status)
{ {
@ -233,6 +251,10 @@ public class StoragePoolVO implements StoragePool, Identity {
public void setPath(String path) { public void setPath(String path) {
this.path = path; this.path = path;
} }
public void setUserInfo(String userInfo) {
this.userInfo = userInfo;
}
@Override @Override
public int getPort() { public int getPort() {

6
debian/changelog vendored
View File

@ -1,3 +1,9 @@
cloud (3.0.2) unstable; urgency=low
* Bumping the package version to the latest release.
-- Wido den Hollander <wido@widodh.nl> Wed, 25 Jul 2012 14:53:31 +0200
cloud (2.2.2) unstable; urgency=low cloud (2.2.2) unstable; urgency=low
* Bumping version number for next CloudStack release * Bumping version number for next CloudStack release

View File

@ -3,6 +3,5 @@
/etc/cloud/agent/environment.properties /etc/cloud/agent/environment.properties
/etc/cloud/agent/log4j-cloud.xml /etc/cloud/agent/log4j-cloud.xml
/etc/init.d/cloud-agent /etc/init.d/cloud-agent
/usr/bin/agent-runner
/usr/bin/cloud-setup-agent /usr/bin/cloud-setup-agent
/var/log/cloud/agent /var/log/cloud/agent

View File

@ -1,6 +1,5 @@
/usr/share/java/cloud-usage.jar /usr/share/java/cloud-usage.jar
/etc/init.d/cloud-usage /etc/init.d/cloud-usage
/usr/bin/usage-runner
/var/log/cloud/usage /var/log/cloud/usage
/etc/cloud/usage/usage-components.xml /etc/cloud/usage/usage-components.xml
/etc/cloud/usage/log4j-cloud_usage.xml /etc/cloud/usage/log4j-cloud_usage.xml

28
debian/control vendored
View File

@ -11,11 +11,11 @@ Provides: vmops-deps
Conflicts: vmops-deps Conflicts: vmops-deps
Replaces: vmops-deps Replaces: vmops-deps
Architecture: any Architecture: any
Depends: openjdk-6-jre, cloud-agent-deps Depends: openjdk-6-jre
Description: CloudStack library dependencies Description: CloudStack library dependencies
This package contains a number of third-party dependencies This package contains a number of third-party dependencies
not shipped by distributions, required to run the CloudStack not shipped by distributions, required to run the CloudStack
Cloud Stack. Management Server.
Package: cloud-agent-deps Package: cloud-agent-deps
Provides: cloud-agent-deps Provides: cloud-agent-deps
@ -26,8 +26,7 @@ Depends: openjdk-6-jre
Description: CloudStack agent library dependencies Description: CloudStack agent library dependencies
This package contains a number of third-party dependencies This package contains a number of third-party dependencies
not shipped by distributions, required to run the CloudStack not shipped by distributions, required to run the CloudStack
Cloud Stack. Agent.
Package: cloud-utils Package: cloud-utils
Provides: vmops-utils Provides: vmops-utils
@ -37,7 +36,7 @@ Architecture: any
Depends: openjdk-6-jre, python Depends: openjdk-6-jre, python
Description: CloudStack utility library Description: CloudStack utility library
The CloudStack utility libraries provide a set of Java classes used The CloudStack utility libraries provide a set of Java classes used
in the CloudStack Cloud Stack. in the CloudStack environment.
Package: cloud-client-ui Package: cloud-client-ui
Provides: vmops-client-ui Provides: vmops-client-ui
@ -59,7 +58,7 @@ Architecture: any
Depends: openjdk-6-jre, cloud-utils (= ${source:Version}), cloud-core (= ${source:Version}), cloud-deps (= ${source:Version}), libservlet2.5-java Depends: openjdk-6-jre, cloud-utils (= ${source:Version}), cloud-core (= ${source:Version}), cloud-deps (= ${source:Version}), libservlet2.5-java
Description: CloudStack server library Description: CloudStack server library
The CloudStack server libraries provide a set of Java classes used The CloudStack server libraries provide a set of Java classes used
in the CloudStack Cloud Stack. in the CloudStack management server.
Package: cloud-agent-scripts Package: cloud-agent-scripts
Provides: vmops-agent-scripts, vmops-console, cloud-console, vmops-console-proxy Provides: vmops-agent-scripts, vmops-console, cloud-console, vmops-console-proxy
@ -68,11 +67,8 @@ Replaces: vmops-agent-scripts, vmops-console, cloud-console, vmops-console-proxy
Architecture: any Architecture: any
Depends: openjdk-6-jre, python, bash, bzip2, gzip, unzip, nfs-common, openssh-client Depends: openjdk-6-jre, python, bash, bzip2, gzip, unzip, nfs-common, openssh-client
Description: CloudStack agent scripts Description: CloudStack agent scripts
The CloudStack agent is in charge of managing shared computing resources in This package contains a number of scripts needed for the CloudStack Agent on KVM
a CloudStack Cloud Stack-powered cloud. Install this package if this computer HyperVisor hosts. The CloudStack Agent depends on this package.
will participate in your cloud -- this is a requirement for the CloudStack
agent.
Package: cloud-core Package: cloud-core
Provides: vmops-core Provides: vmops-core
@ -90,7 +86,7 @@ Provides: vmops-client
Conflicts: vmops-client Conflicts: vmops-client
Replaces: vmops-client Replaces: vmops-client
Architecture: any Architecture: any
Depends: openjdk-6-jre, cloud-deps (= ${source:Version}), cloud-utils (= ${source:Version}), cloud-server (= ${source:Version}), cloud-client-ui (= ${source:Version}), cloud-setup (= ${source:Version}), cloud-agent-scripts (= ${source:Version}), cloud-python (= ${source:Version}), tomcat6, libws-commons-util-java, libcommons-dbcp-java, libcommons-collections-java, libcommons-httpclient-java, sysvinit-utils, chkconfig, sudo, jsvc, python-mysqldb, python-paramiko, augeas-tools, genisoimage, cloud-system-iso Depends: openjdk-6-jre, cloud-deps (= ${source:Version}), cloud-utils (= ${source:Version}), cloud-server (= ${source:Version}), cloud-client-ui (= ${source:Version}), cloud-setup (= ${source:Version}), cloud-python (= ${source:Version}), tomcat6, libws-commons-util-java, libcommons-dbcp-java, libcommons-collections-java, libcommons-httpclient-java, sysvinit-utils, chkconfig, sudo, jsvc, python-mysqldb, python-paramiko, augeas-tools, genisoimage, cloud-system-iso
Description: CloudStack client Description: CloudStack client
The CloudStack management server is the central point of coordination, The CloudStack management server is the central point of coordination,
management, and intelligence in the CloudStack Cloud Stack. This package management, and intelligence in the CloudStack Cloud Stack. This package
@ -123,17 +119,17 @@ Provides: vmops-agent
Conflicts: vmops-agent Conflicts: vmops-agent
Replaces: vmops-agent Replaces: vmops-agent
Architecture: any Architecture: any
Depends: openjdk-6-jre, cloud-utils (= ${source:Version}), cloud-core (= ${source:Version}), cloud-agent-deps (= ${source:Version}), python, cloud-python (= ${source:Version}), cloud-agent-libs (= ${source:Version}), cloud-agent-scripts (= ${source:Version}), libcommons-httpclient-java, libcommons-collections-java, libcommons-dbcp-java, libcommons-pool-java, libcommons-logging-java, libvirt0, sysvinit-utils, chkconfig, qemu-kvm, libvirt-bin, uuid-runtime, rsync, grep, iproute, ebtables, vlan, libcglib-java, libcommons-httpclient-java, libservlet2.5-java, liblog4j1.2-java, libjna-java, wget, jsvc Depends: openjdk-6-jre, cloud-utils (= ${source:Version}), cloud-core (= ${source:Version}), cloud-agent-deps (= ${source:Version}), python, cloud-python (= ${source:Version}), cloud-agent-libs (= ${source:Version}), cloud-agent-scripts (= ${source:Version}), libcommons-httpclient-java, libcommons-collections-java, libcommons-dbcp-java, libcommons-pool-java, libcommons-logging-java, libvirt0, sysvinit-utils, chkconfig, qemu-kvm, libvirt-bin, uuid-runtime, rsync, grep, iproute, ebtables, vlan, libcglib-java, libcommons-httpclient-java, libservlet2.5-java, liblog4j1.2-java, libjna-java, wget, jsvc, lsb-base (>= 3.2)
Description: CloudStack agent Description: CloudStack agent
The CloudStack agent is in charge of managing shared computing resources in The CloudStack agent is in charge of managing shared computing resources in
a CloudStack Cloud Stack-powered cloud. Install this package if this computer a CloudStack powered cloud. Install this package if this computer
will participate in your cloud. will participate in your cloud as a KVM HyperVisor.
Package: cloud-system-iso Package: cloud-system-iso
Architecture: any Architecture: any
Description: CloudStack system iso Description: CloudStack system iso
The CloudStack agent is in charge of managing shared computing resources in The CloudStack agent is in charge of managing shared computing resources in
a CloudStack Cloud Stack-powered cloud. Install this package if this computer a CloudStack powered cloud. Install this package if this computer
will participate in your cloud. will participate in your cloud.
Package: cloud-usage Package: cloud-usage

View File

@ -105,7 +105,7 @@
<target name="init" description="Initialize binaries directory"> <target name="init" description="Initialize binaries directory">
<mkdir dir="${classes.dir}/${user-concentrated-pod.jar}"/> <mkdir dir="${classes.dir}/${dp-user-concentrated-pod.jar}"/>
<mkdir dir="${jar.dir}"/> <mkdir dir="${jar.dir}"/>
</target> </target>

View File

@ -716,7 +716,7 @@ public class OvmResourceBase implements ServerResource, HypervisorResource {
vm = OvmVm.getDetails(_conn, vmName); vm = OvmVm.getDetails(_conn, vmName);
} catch (XmlRpcException e) { } catch (XmlRpcException e) {
s_logger.debug("Unable to get details of vm: " + vmName + ", treating it as stopped", e); s_logger.debug("Unable to get details of vm: " + vmName + ", treating it as stopped", e);
return new StopAnswer(cmd, "success", 0, 0L, 0L); return new StopAnswer(cmd, "success", 0, true);
} }
deleteAllNetworkRulesForVm(vmName); deleteAllNetworkRulesForVm(vmName);
@ -724,10 +724,10 @@ public class OvmResourceBase implements ServerResource, HypervisorResource {
cleanup(vm); cleanup(vm);
state = State.Stopped; state = State.Stopped;
return new StopAnswer(cmd, "success", 0, 0L, 0L); return new StopAnswer(cmd, "success", 0, true);
} catch (Exception e) { } catch (Exception e) {
s_logger.debug("Stop " + vmName + "failed", e); s_logger.debug("Stop " + vmName + "failed", e);
return new StopAnswer(cmd, e.getMessage()); return new StopAnswer(cmd, e.getMessage(), false);
} finally { } finally {
synchronized(_vms) { synchronized(_vms) {
if (state != null) { if (state != null) {
@ -749,10 +749,10 @@ public class OvmResourceBase implements ServerResource, HypervisorResource {
try { try {
Map<String, String> res = OvmVm.reboot(_conn, vmName); Map<String, String> res = OvmVm.reboot(_conn, vmName);
Integer vncPort = Integer.parseInt(res.get("vncPort")); Integer vncPort = Integer.parseInt(res.get("vncPort"));
return new RebootAnswer(cmd, null, null, null, vncPort); return new RebootAnswer(cmd, null, vncPort);
} catch (Exception e) { } catch (Exception e) {
s_logger.debug("Reboot " + vmName + " failed", e); s_logger.debug("Reboot " + vmName + " failed", e);
return new RebootAnswer(cmd, e.getMessage()); return new RebootAnswer(cmd, e.getMessage(), false);
} finally { } finally {
synchronized(_vms) { synchronized(_vms) {
_vms.put(cmd.getVmName(), State.Running); _vms.put(cmd.getVmName(), State.Running);

View File

@ -2027,16 +2027,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK, "0"); vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK, "0");
if (getVmState(vmMo) != State.Stopped) { if (getVmState(vmMo) != State.Stopped) {
Long bytesSent = 0L;
Long bytesRcvd = 0L;
if (VirtualMachineName.isValidRouterName(cmd.getVmName())) {
if (cmd.getPrivateRouterIpAddress() != null) {
long[] stats = getNetworkStats(cmd.getPrivateRouterIpAddress());
bytesSent = stats[0];
bytesRcvd = stats[1];
}
}
// before we stop VM, remove all possible snapshots on the VM to let // before we stop VM, remove all possible snapshots on the VM to let
// disk chain be collapsed // disk chain be collapsed
@ -2044,11 +2034,11 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
vmMo.removeAllSnapshots(); vmMo.removeAllSnapshots();
if (vmMo.safePowerOff(_shutdown_waitMs)) { if (vmMo.safePowerOff(_shutdown_waitMs)) {
state = State.Stopped; state = State.Stopped;
return new StopAnswer(cmd, "Stop VM " + cmd.getVmName() + " Succeed", 0, bytesSent, bytesRcvd); return new StopAnswer(cmd, "Stop VM " + cmd.getVmName() + " Succeed", 0, true);
} else { } else {
String msg = "Have problem in powering off VM " + cmd.getVmName() + ", let the process continue"; String msg = "Have problem in powering off VM " + cmd.getVmName() + ", let the process continue";
s_logger.warn(msg); s_logger.warn(msg);
return new StopAnswer(cmd, msg, 0, 0L, 0L); return new StopAnswer(cmd, msg, 0, true);
} }
} else { } else {
state = State.Stopped; state = State.Stopped;
@ -2056,7 +2046,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
String msg = "VM " + cmd.getVmName() + " is already in stopped state"; String msg = "VM " + cmd.getVmName() + " is already in stopped state";
s_logger.info(msg); s_logger.info(msg);
return new StopAnswer(cmd, msg, 0, 0L, 0L); return new StopAnswer(cmd, msg, 0, true);
} finally { } finally {
synchronized (_vms) { synchronized (_vms) {
_vms.put(cmd.getVmName(), state); _vms.put(cmd.getVmName(), state);
@ -2069,7 +2059,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
String msg = "VM " + cmd.getVmName() + " is no longer in vSphere"; String msg = "VM " + cmd.getVmName() + " is no longer in vSphere";
s_logger.info(msg); s_logger.info(msg);
return new StopAnswer(cmd, msg, 0, 0L, 0L); return new StopAnswer(cmd, msg, 0, true);
} }
} catch (Exception e) { } catch (Exception e) {
if (e instanceof RemoteException) { if (e instanceof RemoteException) {
@ -2079,7 +2069,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
String msg = "StopCommand failed due to " + VmwareHelper.getExceptionMessage(e); String msg = "StopCommand failed due to " + VmwareHelper.getExceptionMessage(e);
s_logger.error(msg); s_logger.error(msg);
return new StopAnswer(cmd, msg); return new StopAnswer(cmd, msg, false);
} }
} }
@ -2088,17 +2078,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
s_logger.info("Executing resource RebootRouterCommand: " + _gson.toJson(cmd)); s_logger.info("Executing resource RebootRouterCommand: " + _gson.toJson(cmd));
} }
Long bytesSent = 0L;
Long bytesRcvd = 0L;
if (VirtualMachineName.isValidRouterName(cmd.getVmName())) {
long[] stats = getNetworkStats(cmd.getPrivateIpAddress());
bytesSent = stats[0];
bytesRcvd = stats[1];
}
RebootAnswer answer = (RebootAnswer) execute((RebootCommand) cmd); RebootAnswer answer = (RebootAnswer) execute((RebootCommand) cmd);
answer.setBytesSent(bytesSent);
answer.setBytesReceived(bytesRcvd);
if (answer.getResult()) { if (answer.getResult()) {
String connectResult = connect(cmd.getVmName(), cmd.getPrivateIpAddress()); String connectResult = connect(cmd.getVmName(), cmd.getPrivateIpAddress());
@ -2124,7 +2104,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
if (vmMo != null) { if (vmMo != null) {
try { try {
vmMo.rebootGuest(); vmMo.rebootGuest();
return new RebootAnswer(cmd, "reboot succeeded", null, null); return new RebootAnswer(cmd, "reboot succeeded", true);
} catch(ToolsUnavailable e) { } catch(ToolsUnavailable e) {
s_logger.warn("VMware tools is not installed at guest OS, we will perform hard reset for reboot"); s_logger.warn("VMware tools is not installed at guest OS, we will perform hard reset for reboot");
} catch(Exception e) { } catch(Exception e) {
@ -2133,16 +2113,16 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
// continue to try with hard-reset // continue to try with hard-reset
if (vmMo.reset()) { if (vmMo.reset()) {
return new RebootAnswer(cmd, "reboot succeeded", null, null); return new RebootAnswer(cmd, "reboot succeeded", true);
} }
String msg = "Reboot failed in vSphere. vm: " + cmd.getVmName(); String msg = "Reboot failed in vSphere. vm: " + cmd.getVmName();
s_logger.warn(msg); s_logger.warn(msg);
return new RebootAnswer(cmd, msg); return new RebootAnswer(cmd, msg, false);
} else { } else {
String msg = "Unable to find the VM in vSphere to reboot. vm: " + cmd.getVmName(); String msg = "Unable to find the VM in vSphere to reboot. vm: " + cmd.getVmName();
s_logger.warn(msg); s_logger.warn(msg);
return new RebootAnswer(cmd, msg); return new RebootAnswer(cmd, msg, false);
} }
} catch (Exception e) { } catch (Exception e) {
if (e instanceof RemoteException) { if (e instanceof RemoteException) {
@ -2152,7 +2132,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
String msg = "RebootCommand failed due to " + VmwareHelper.getExceptionMessage(e); String msg = "RebootCommand failed due to " + VmwareHelper.getExceptionMessage(e);
s_logger.error(msg); s_logger.error(msg);
return new RebootAnswer(cmd, msg); return new RebootAnswer(cmd, msg, false);
} }
} }
@ -2786,8 +2766,18 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
if (s_logger.isInfoEnabled()) { if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource PingTestCommand: " + _gson.toJson(cmd)); s_logger.info("Executing resource PingTestCommand: " + _gson.toJson(cmd));
} }
String controlIp = cmd.getRouterIp();
String args = " -c 1 -n -q " + cmd.getPrivateIp();
try {
VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
Pair<Boolean, String> result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null, "/bin/ping" + args);
if(result.first())
return new Answer(cmd); return new Answer(cmd);
} catch (Exception e) {
s_logger.error("Unable to execute ping command on DomR (" + controlIp + "), domR may not be ready yet. failure due to "
+ VmwareHelper.getExceptionMessage(e), e);
}
return new Answer(cmd,false,"PingTestCommand failed");
} }
protected Answer execute(CheckOnHostCommand cmd) { protected Answer execute(CheckOnHostCommand cmd) {

View File

@ -216,7 +216,6 @@ import com.cloud.utils.net.NetUtils;
import com.cloud.vm.DiskProfile; import com.cloud.vm.DiskProfile;
import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.VirtualMachineName;
import com.trilead.ssh2.SCPClient; import com.trilead.ssh2.SCPClient;
import com.xensource.xenapi.Bond; import com.xensource.xenapi.Bond;
import com.xensource.xenapi.Connection; import com.xensource.xenapi.Connection;
@ -2855,10 +2854,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
vms = VM.getByNameLabel(conn, cmd.getVmName()); vms = VM.getByNameLabel(conn, cmd.getVmName());
} catch (XenAPIException e0) { } catch (XenAPIException e0) {
s_logger.debug("getByNameLabel failed " + e0.toString()); s_logger.debug("getByNameLabel failed " + e0.toString());
return new RebootAnswer(cmd, "getByNameLabel failed " + e0.toString()); return new RebootAnswer(cmd, "getByNameLabel failed " + e0.toString(), false);
} catch (Exception e0) { } catch (Exception e0) {
s_logger.debug("getByNameLabel failed " + e0.getMessage()); s_logger.debug("getByNameLabel failed " + e0.getMessage());
return new RebootAnswer(cmd, "getByNameLabel failed"); return new RebootAnswer(cmd, "getByNameLabel failed", false);
} }
for (VM vm : vms) { for (VM vm : vms) {
try { try {
@ -2866,10 +2865,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
} catch (Exception e) { } catch (Exception e) {
String msg = e.toString(); String msg = e.toString();
s_logger.warn(msg, e); s_logger.warn(msg, e);
return new RebootAnswer(cmd, msg); return new RebootAnswer(cmd, msg, false);
} }
} }
return new RebootAnswer(cmd, "reboot succeeded", null, null); return new RebootAnswer(cmd, "reboot succeeded", true);
} finally { } finally {
synchronized (_cluster.intern()) { synchronized (_cluster.intern()) {
s_vms.put(_cluster, _name, cmd.getVmName(), State.Running); s_vms.put(_cluster, _name, cmd.getVmName(), State.Running);
@ -2880,16 +2879,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
protected Answer execute(RebootRouterCommand cmd) { protected Answer execute(RebootRouterCommand cmd) {
Connection conn = getConnection(); Connection conn = getConnection();
Long bytesSent = 0L;
Long bytesRcvd = 0L;
if (VirtualMachineName.isValidRouterName(cmd.getVmName())) {
long[] stats = getNetworkStats(conn, cmd.getPrivateIpAddress());
bytesSent = stats[0];
bytesRcvd = stats[1];
}
RebootAnswer answer = execute((RebootCommand) cmd); RebootAnswer answer = execute((RebootCommand) cmd);
answer.setBytesSent(bytesSent);
answer.setBytesReceived(bytesRcvd);
if (answer.getResult()) { if (answer.getResult()) {
String cnct = connect(conn, cmd.getVmName(), cmd.getPrivateIpAddress()); String cnct = connect(conn, cmd.getVmName(), cmd.getPrivateIpAddress());
networkUsage(conn, cmd.getPrivateIpAddress(), "create", null); networkUsage(conn, cmd.getPrivateIpAddress(), "create", null);
@ -3352,23 +3342,21 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
s_logger.info("VM does not exist on XenServer" + _host.uuid); s_logger.info("VM does not exist on XenServer" + _host.uuid);
s_vms.remove(_cluster, _name, vmName); s_vms.remove(_cluster, _name, vmName);
} }
return new StopAnswer(cmd, "VM does not exist", 0 , 0L, 0L); return new StopAnswer(cmd, "VM does not exist", 0 , true);
} }
Long bytesSent = 0L;
Long bytesRcvd = 0L;
for (VM vm : vms) { for (VM vm : vms) {
VM.Record vmr = vm.getRecord(conn); VM.Record vmr = vm.getRecord(conn);
if (vmr.isControlDomain) { if (vmr.isControlDomain) {
String msg = "Tring to Shutdown control domain"; String msg = "Tring to Shutdown control domain";
s_logger.warn(msg); s_logger.warn(msg);
return new StopAnswer(cmd, msg); return new StopAnswer(cmd, msg, false);
} }
if (vmr.powerState == VmPowerState.RUNNING && !isRefNull(vmr.residentOn) && !vmr.residentOn.getUuid(conn).equals(_host.uuid)) { if (vmr.powerState == VmPowerState.RUNNING && !isRefNull(vmr.residentOn) && !vmr.residentOn.getUuid(conn).equals(_host.uuid)) {
String msg = "Stop Vm " + vmName + " failed due to this vm is not running on this host: " + _host.uuid + " but host:" + vmr.residentOn.getUuid(conn); String msg = "Stop Vm " + vmName + " failed due to this vm is not running on this host: " + _host.uuid + " but host:" + vmr.residentOn.getUuid(conn);
s_logger.warn(msg); s_logger.warn(msg);
return new StopAnswer(cmd, msg); return new StopAnswer(cmd, msg, false);
} }
State state = s_vms.getState(_cluster, vmName); State state = s_vms.getState(_cluster, vmName);
@ -3382,13 +3370,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
if (vmr.powerState == VmPowerState.RUNNING) { if (vmr.powerState == VmPowerState.RUNNING) {
/* when stop a vm, set affinity to current xenserver */ /* when stop a vm, set affinity to current xenserver */
vm.setAffinity(conn, vm.getResidentOn(conn)); vm.setAffinity(conn, vm.getResidentOn(conn));
if (VirtualMachineName.isValidRouterName(vmName)) {
if (cmd.getPrivateRouterIpAddress() != null) {
long[] stats = getNetworkStats(conn, cmd.getPrivateRouterIpAddress());
bytesSent = stats[0];
bytesRcvd = stats[1];
}
}
if (_canBridgeFirewall) { if (_canBridgeFirewall) {
String result = callHostPlugin(conn, "vmops", "destroy_network_rules_for_vm", "vmName", cmd String result = callHostPlugin(conn, "vmops", "destroy_network_rules_for_vm", "vmName", cmd
.getVmName()); .getVmName());
@ -3403,7 +3385,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
} catch (Exception e) { } catch (Exception e) {
String msg = "Catch exception " + e.getClass().getName() + " when stop VM:" + cmd.getVmName() + " due to " + e.toString(); String msg = "Catch exception " + e.getClass().getName() + " when stop VM:" + cmd.getVmName() + " due to " + e.toString();
s_logger.debug(msg); s_logger.debug(msg);
return new StopAnswer(cmd, msg); return new StopAnswer(cmd, msg, false);
} finally { } finally {
try { try {
@ -3428,7 +3410,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
disableVlanNetwork(conn, network); disableVlanNetwork(conn, network);
} }
} }
return new StopAnswer(cmd, "Stop VM " + vmName + " Succeed", 0, bytesSent, bytesRcvd); return new StopAnswer(cmd, "Stop VM " + vmName + " Succeed", 0, true);
} }
} catch (XenAPIException e) { } catch (XenAPIException e) {
String msg = "VM destroy failed in Stop " + vmName + " Command due to " + e.toString(); String msg = "VM destroy failed in Stop " + vmName + " Command due to " + e.toString();
@ -3448,16 +3430,16 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
} catch (XenAPIException e) { } catch (XenAPIException e) {
String msg = "Stop Vm " + vmName + " fail due to " + e.toString(); String msg = "Stop Vm " + vmName + " fail due to " + e.toString();
s_logger.warn(msg, e); s_logger.warn(msg, e);
return new StopAnswer(cmd, msg); return new StopAnswer(cmd, msg, false);
} catch (XmlRpcException e) { } catch (XmlRpcException e) {
String msg = "Stop Vm " + vmName + " fail due to " + e.getMessage(); String msg = "Stop Vm " + vmName + " fail due to " + e.getMessage();
s_logger.warn(msg, e); s_logger.warn(msg, e);
return new StopAnswer(cmd, msg); return new StopAnswer(cmd, msg, false);
} catch (Exception e) { } catch (Exception e) {
s_logger.warn("Unable to stop " + vmName + " due to ", e); s_logger.warn("Unable to stop " + vmName + " due to ", e);
return new StopAnswer(cmd, e); return new StopAnswer(cmd, e);
} }
return new StopAnswer(cmd, "Stop VM failed"); return new StopAnswer(cmd, "Stop VM failed", false);
} }
private List<VDI> getVdis(Connection conn, VM vm) { private List<VDI> getVdis(Connection conn, VM vm) {

View File

@ -1032,4 +1032,9 @@ public class ElasticLoadBalancerManagerImpl implements
// TODO Auto-generated method stub // TODO Auto-generated method stub
return false; return false;
} }
@Override
public void prepareStop(VirtualMachineProfile<DomainRouterVO> profile) {
}
} }

View File

@ -16,3 +16,8 @@ announce that they have accepted.
Being a committer enables easier contribution to the Being a committer enables easier contribution to the
project since there is no need to go via the patch project since there is no need to go via the patch
submission process. This should enable better productivity. submission process. This should enable better productivity.
Please join me in congratulating #########
--#####Name####
on behalf of the CloudStack PPMC

View File

@ -133,14 +133,14 @@ write_hbLog() {
} }
check_hbLog() { check_hbLog() {
oldTimeStamp=$(cat $hbFile) now=$(date +%s)
sleep $interval &> /dev/null hb=$(cat $hbFile)
newTimeStamp=$(cat $hbFile) diff=`expr $now - $hb`
if [ $newTimeStamp -gt $oldTimeStamp ] if [ $diff -gt $interval ]
then then
return 0 return 1
fi fi
return 1 return 0
} }
if [ "$rflag" == "1" ] if [ "$rflag" == "1" ]

View File

@ -428,10 +428,10 @@ public class BareMetalResourceBase implements ServerResource {
protected RebootAnswer execute(final RebootCommand cmd) { protected RebootAnswer execute(final RebootCommand cmd) {
if (!doScript(_rebootCommand)) { if (!doScript(_rebootCommand)) {
return new RebootAnswer(cmd, "IPMI reboot failed"); return new RebootAnswer(cmd, "IPMI reboot failed", false);
} }
return new RebootAnswer(cmd, "reboot succeeded", null, null); return new RebootAnswer(cmd, "reboot succeeded", true);
} }
protected StopAnswer execute(final StopCommand cmd) { protected StopAnswer execute(final StopCommand cmd) {
@ -466,7 +466,7 @@ public class BareMetalResourceBase implements ServerResource {
count++; count++;
} }
return success ? new StopAnswer(cmd, "Success", null, Long.valueOf(0), Long.valueOf(0)) : new StopAnswer(cmd, "IPMI power off failed"); return success ? new StopAnswer(cmd, "Success", null, true) : new StopAnswer(cmd, "IPMI power off failed", false);
} }
protected StartAnswer execute(StartCommand cmd) { protected StartAnswer execute(StartCommand cmd) {

View File

@ -375,4 +375,8 @@ public class AgentBasedConsoleProxyManager implements ConsoleProxyManager, Virtu
// TODO Auto-generated method stub // TODO Auto-generated method stub
return false; return false;
} }
@Override
public void prepareStop(VirtualMachineProfile<ConsoleProxyVO> profile) {
}
} }

View File

@ -2032,4 +2032,8 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx
// TODO Auto-generated method stub // TODO Auto-generated method stub
return false; return false;
} }
@Override
public void prepareStop(VirtualMachineProfile<ConsoleProxyVO> profile) {
}
} }

View File

@ -17,10 +17,12 @@
package com.cloud.deploy; package com.cloud.deploy;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.TreeSet;
import javax.ejb.Local; import javax.ejb.Local;
import javax.naming.ConfigurationException; import javax.naming.ConfigurationException;
@ -55,6 +57,7 @@ import com.cloud.org.Cluster;
import com.cloud.org.Grouping; import com.cloud.org.Grouping;
import com.cloud.resource.ResourceState; import com.cloud.resource.ResourceState;
import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolHostVO; import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.StoragePoolVO; import com.cloud.storage.StoragePoolVO;
@ -98,6 +101,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
@Inject protected StoragePoolDao _storagePoolDao; @Inject protected StoragePoolDao _storagePoolDao;
@Inject protected CapacityDao _capacityDao; @Inject protected CapacityDao _capacityDao;
@Inject protected AccountManager _accountMgr; @Inject protected AccountManager _accountMgr;
@Inject protected StorageManager _storageMgr;
@Inject(adapter=StoragePoolAllocator.class) @Inject(adapter=StoragePoolAllocator.class)
protected Adapters<StoragePoolAllocator> _storagePoolAllocators; protected Adapters<StoragePoolAllocator> _storagePoolAllocators;
@ -638,25 +642,56 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
s_logger.debug("Trying to find a potenial host and associated storage pools from the suitable host/pool lists for this VM"); s_logger.debug("Trying to find a potenial host and associated storage pools from the suitable host/pool lists for this VM");
boolean hostCanAccessPool = false; boolean hostCanAccessPool = false;
boolean haveEnoughSpace = false;
Map<Volume, StoragePool> storage = new HashMap<Volume, StoragePool>(); Map<Volume, StoragePool> storage = new HashMap<Volume, StoragePool>();
TreeSet<Volume> volumesOrderBySizeDesc = new TreeSet<Volume>(new Comparator<Volume>() {
@Override
public int compare(Volume v1, Volume v2) {
if(v1.getSize() < v2.getSize())
return 1;
else
return -1;
}
});
volumesOrderBySizeDesc.addAll(suitableVolumeStoragePools.keySet());
boolean multipleVolume = volumesOrderBySizeDesc.size() > 1;
for(Host potentialHost : suitableHosts){ for(Host potentialHost : suitableHosts){
for(Volume vol : suitableVolumeStoragePools.keySet()){ Map<StoragePool,List<Volume>> volumeAllocationMap = new HashMap<StoragePool,List<Volume>>();
for(Volume vol : volumesOrderBySizeDesc){
haveEnoughSpace = false;
s_logger.debug("Checking if host: "+potentialHost.getId() +" can access any suitable storage pool for volume: "+ vol.getVolumeType()); s_logger.debug("Checking if host: "+potentialHost.getId() +" can access any suitable storage pool for volume: "+ vol.getVolumeType());
List<StoragePool> volumePoolList = suitableVolumeStoragePools.get(vol); List<StoragePool> volumePoolList = suitableVolumeStoragePools.get(vol);
hostCanAccessPool = false; hostCanAccessPool = false;
for(StoragePool potentialSPool : volumePoolList){ for(StoragePool potentialSPool : volumePoolList){
if(hostCanAccessSPool(potentialHost, potentialSPool)){ if(hostCanAccessSPool(potentialHost, potentialSPool)){
storage.put(vol, potentialSPool);
hostCanAccessPool = true; hostCanAccessPool = true;
if(multipleVolume){
List<Volume> requestVolumes = null;
if(volumeAllocationMap.containsKey(potentialSPool))
requestVolumes = volumeAllocationMap.get(potentialSPool);
else
requestVolumes = new ArrayList<Volume>();
requestVolumes.add(vol);
if(!_storageMgr.storagePoolHasEnoughSpace(requestVolumes, potentialSPool))
continue;
volumeAllocationMap.put(potentialSPool,requestVolumes);
}
storage.put(vol, potentialSPool);
haveEnoughSpace = true;
break; break;
} }
} }
if(!hostCanAccessPool){ if(!hostCanAccessPool){
break; break;
} }
if(!haveEnoughSpace) {
s_logger.warn("insufficient capacity to allocate all volumes");
break;
}
} }
if(hostCanAccessPool){ if(hostCanAccessPool && haveEnoughSpace){
s_logger.debug("Found a potential host " + "id: "+potentialHost.getId() + " name: " +potentialHost.getName()+ " and associated storage pools for this VM"); s_logger.debug("Found a potential host " + "id: "+potentialHost.getId() + " name: " +potentialHost.getName() + " and associated storage pools for this VM");
return new Pair<Host, Map<Volume, StoragePool>>(potentialHost, storage); return new Pair<Host, Map<Volume, StoragePool>>(potentialHost, storage);
} }
} }

View File

@ -3449,6 +3449,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
} }
} }
sc.addAnd("id", SearchCriteria.Op.SC, accountSC);
return _networksDao.search(sc, searchFilter); return _networksDao.search(sc, searchFilter);
} }

View File

@ -502,34 +502,13 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
final UserStatisticsVO userStats = _userStatsDao.lock(router.getAccountId(), router.getDataCenterIdToDeployIn(), final UserStatisticsVO userStats = _userStatsDao.lock(router.getAccountId(), router.getDataCenterIdToDeployIn(),
guestNtwkId, null, router.getId(), router.getType().toString()); guestNtwkId, null, router.getId(), router.getType().toString());
if (userStats != null) { if (userStats != null) {
final RebootAnswer sa = (RebootAnswer) answer; final long currentBytesRcvd = userStats.getCurrentBytesReceived();
final Long received = sa.getBytesReceived();
long netBytes = 0;
if (received != null) {
if (received.longValue() >= userStats.getCurrentBytesReceived()) {
netBytes = received.longValue();
} else {
netBytes = userStats.getCurrentBytesReceived() + received;
}
} else {
netBytes = userStats.getCurrentBytesReceived();
}
userStats.setCurrentBytesReceived(0); userStats.setCurrentBytesReceived(0);
userStats.setNetBytesReceived(userStats.getNetBytesReceived() + netBytes); userStats.setNetBytesReceived(userStats.getNetBytesReceived() + currentBytesRcvd);
final Long sent = sa.getBytesSent(); final long currentBytesSent = userStats.getCurrentBytesSent();
if (sent != null) {
if (sent.longValue() >= userStats.getCurrentBytesSent()) {
netBytes = sent.longValue();
} else {
netBytes = userStats.getCurrentBytesSent() + sent;
}
} else {
netBytes = userStats.getCurrentBytesSent();
}
userStats.setNetBytesSent(userStats.getNetBytesSent() + netBytes);
userStats.setCurrentBytesSent(0); userStats.setCurrentBytesSent(0);
userStats.setNetBytesSent(userStats.getNetBytesSent() + currentBytesSent);
_userStatsDao.update(userStats.getId(), userStats); _userStatsDao.update(userStats.getId(), userStats);
s_logger.debug("Successfully updated user statistics as a part of domR " + router + " reboot/stop"); s_logger.debug("Successfully updated user statistics as a part of domR " + router + " reboot/stop");
} else { } else {
@ -540,7 +519,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
txn.commit(); txn.commit();
} catch (final Exception e) { } catch (final Exception e) {
txn.rollback(); txn.rollback();
throw new CloudRuntimeException("Problem getting stats after reboot/stop ", e); throw new CloudRuntimeException("Problem updating stats after reboot/stop ", e);
} }
} }
@ -3221,4 +3200,99 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
return false; return false;
} }
@Override
public void prepareStop(VirtualMachineProfile<DomainRouterVO> profile){
//Collect network usage before stopping Vm
VMInstanceVO vm = profile.getVirtualMachine();
DomainRouterVO router = _routerDao.findById(vm.getId());
if(router == null){
return;
}
/*String privateIP = router.getPrivateIpAddress();
if (privateIP != null) {
List<Long> routerGuestNtwkIds = _routerDao.getRouterNetworks(router.getId());
for (Long guestNtwkId : routerGuestNtwkIds) {
boolean forVpc = router.getVpcId() != null;
Network guestNtwk = _networkMgr.getNetwork(guestNtwkId);
Nic guestNic = _nicDao.findByInstanceIdAndNetworkId(guestNtwk.getId(), router.getId());
NicProfile guestNicProfile = new NicProfile(guestNic, guestNtwk, guestNic.getBroadcastUri(),
guestNic.getIsolationUri(), _networkMgr.getNetworkRate(guestNtwk.getId(), router.getId()),
_networkMgr.isSecurityGroupSupportedInNetwork(guestNtwk),
_networkMgr.getNetworkTag(router.getHypervisorType(), guestNtwk));
final NetworkUsageCommand usageCmd = new NetworkUsageCommand(privateIP, router.getHostName(),
forVpc, _itMgr.toNicTO(guestNicProfile, router.getHypervisorType()));
UserStatisticsVO previousStats = _statsDao.findBy(router.getAccountId(),
router.getDataCenterIdToDeployIn(), guestNtwkId, null, router.getId(), router.getType().toString());
NetworkUsageAnswer answer = null;
try {
answer = (NetworkUsageAnswer) _agentMgr.easySend(router.getHostId(), usageCmd);
} catch (Exception e) {
s_logger.warn("Error while collecting network stats from router: "+router.getInstanceName()+" from host: "+router.getHostId(), e);
continue;
}
if (answer != null) {
if (!answer.getResult()) {
s_logger.warn("Error while collecting network stats from router: "+router.getInstanceName()+" from host: "+router.getHostId() + "; details: " + answer.getDetails());
continue;
}
Transaction txn = Transaction.open(Transaction.CLOUD_DB);
try {
if ((answer.getBytesReceived() == 0) && (answer.getBytesSent() == 0)) {
s_logger.debug("Recieved and Sent bytes are both 0. Not updating user_statistics");
continue;
}
txn.start();
UserStatisticsVO stats = _statsDao.lock(router.getAccountId(),
router.getDataCenterIdToDeployIn(), guestNtwkId, null, router.getId(), router.getType().toString());
if (stats == null) {
s_logger.warn("unable to find stats for account: " + router.getAccountId());
continue;
}
if(previousStats != null
&& ((previousStats.getCurrentBytesReceived() != stats.getCurrentBytesReceived())
|| (previousStats.getCurrentBytesSent() != stats.getCurrentBytesSent()))){
s_logger.debug("Router stats changed from the time NetworkUsageCommand was sent. " +
"Ignoring current answer. Router: "+answer.getRouterName()+" Rcvd: " +
answer.getBytesReceived()+ "Sent: " +answer.getBytesSent());
continue;
}
if (stats.getCurrentBytesReceived() > answer.getBytesReceived()) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Received # of bytes that's less than the last one. " +
"Assuming something went wrong and persisting it. Router: " +
answer.getRouterName()+" Reported: " + answer.getBytesReceived()
+ " Stored: " + stats.getCurrentBytesReceived());
}
stats.setNetBytesReceived(stats.getNetBytesReceived() + stats.getCurrentBytesReceived());
}
stats.setCurrentBytesReceived(answer.getBytesReceived());
if (stats.getCurrentBytesSent() > answer.getBytesSent()) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Received # of bytes that's less than the last one. " +
"Assuming something went wrong and persisting it. Router: " +
answer.getRouterName()+" Reported: " + answer.getBytesSent()
+ " Stored: " + stats.getCurrentBytesSent());
}
stats.setNetBytesSent(stats.getNetBytesSent() + stats.getCurrentBytesSent());
}
stats.setCurrentBytesSent(answer.getBytesSent());
_statsDao.update(stats.getId(), stats);
txn.commit();
} catch (Exception e) {
txn.rollback();
s_logger.warn("Unable to update user statistics for account: " + router.getAccountId()
+ " Rx: " + answer.getBytesReceived() + "; Tx: " + answer.getBytesSent());
} finally {
txn.close();
}
}
}
}*/
}
} }

View File

@ -27,7 +27,6 @@ import javax.naming.ConfigurationException;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import com.citrix.netscaler.nitro.resource.config.network.vlan;
import com.cloud.api.commands.ListPortForwardingRulesCmd; import com.cloud.api.commands.ListPortForwardingRulesCmd;
import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.ConfigurationManager;
import com.cloud.domain.dao.DomainDao; import com.cloud.domain.dao.DomainDao;
@ -372,10 +371,12 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
} }
@Override @Override
@ActionEvent(eventType = EventTypes.EVENT_ENABLE_STATIC_NAT, eventDescription = "enabling static nat")
public boolean enableStaticNat(long ipId, long vmId, long networkId, boolean isSystemVm) public boolean enableStaticNat(long ipId, long vmId, long networkId, boolean isSystemVm)
throws NetworkRuleConflictException, ResourceUnavailableException { throws NetworkRuleConflictException, ResourceUnavailableException {
UserContext ctx = UserContext.current(); UserContext ctx = UserContext.current();
Account caller = ctx.getCaller(); Account caller = ctx.getCaller();
UserContext.current().setEventDetails("Ip Id: " + ipId);
// Verify input parameters // Verify input parameters
@ -1136,6 +1137,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
} }
@Override @Override
@ActionEvent(eventType = EventTypes.EVENT_DISABLE_STATIC_NAT, eventDescription = "disabling static nat", async=true)
public boolean disableStaticNat(long ipId) throws ResourceUnavailableException, NetworkRuleConflictException, InsufficientAddressCapacityException { public boolean disableStaticNat(long ipId) throws ResourceUnavailableException, NetworkRuleConflictException, InsufficientAddressCapacityException {
UserContext ctx = UserContext.current(); UserContext ctx = UserContext.current();
Account caller = ctx.getCaller(); Account caller = ctx.getCaller();

View File

@ -235,4 +235,6 @@ public interface StorageManager extends StorageService, Manager {
String getSupportedImageFormatForCluster(Long clusterId); String getSupportedImageFormatForCluster(Long clusterId);
HypervisorType getHypervisorTypeFromFormat(ImageFormat format); HypervisorType getHypervisorTypeFromFormat(ImageFormat format);
}
boolean storagePoolHasEnoughSpace(List<Volume> volume, StoragePool pool);
}

View File

@ -80,6 +80,7 @@ import com.cloud.api.commands.UpdateStoragePoolCmd;
import com.cloud.api.commands.UploadVolumeCmd; import com.cloud.api.commands.UploadVolumeCmd;
import com.cloud.async.AsyncJobManager; import com.cloud.async.AsyncJobManager;
import com.cloud.capacity.Capacity; import com.cloud.capacity.Capacity;
import com.cloud.capacity.CapacityManager;
import com.cloud.capacity.CapacityState; import com.cloud.capacity.CapacityState;
import com.cloud.capacity.CapacityVO; import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDao; import com.cloud.capacity.dao.CapacityDao;
@ -133,6 +134,7 @@ import com.cloud.resource.ResourceManager;
import com.cloud.resource.ResourceState; import com.cloud.resource.ResourceState;
import com.cloud.server.ManagementServer; import com.cloud.server.ManagementServer;
import com.cloud.server.ResourceTag.TaggedResourceType; import com.cloud.server.ResourceTag.TaggedResourceType;
import com.cloud.server.StatsCollector;
import com.cloud.service.ServiceOfferingVO; import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.ImageFormat;
@ -274,6 +276,8 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
@Inject @Inject
protected CapacityDao _capacityDao; protected CapacityDao _capacityDao;
@Inject @Inject
protected CapacityManager _capacityMgr;
@Inject
protected DiskOfferingDao _diskOfferingDao; protected DiskOfferingDao _diskOfferingDao;
@Inject @Inject
protected AccountDao _accountDao; protected AccountDao _accountDao;
@ -352,6 +356,9 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
private StateMachine2<Volume.State, Volume.Event, Volume> _volStateMachine; private StateMachine2<Volume.State, Volume.Event, Volume> _volStateMachine;
private int _customDiskOfferingMinSize = 1; private int _customDiskOfferingMinSize = 1;
private int _customDiskOfferingMaxSize = 1024; private int _customDiskOfferingMaxSize = 1024;
private double _storageUsedThreshold = 1.0d;
private double _storageAllocatedThreshold = 1.0d;
protected BigDecimal _storageOverprovisioningFactor = new BigDecimal(1);
public boolean share(VMInstanceVO vm, List<VolumeVO> vols, HostVO host, boolean cancelPreviousShare) throws StorageUnavailableException { public boolean share(VMInstanceVO vm, List<VolumeVO> vols, HostVO host, boolean cancelPreviousShare) throws StorageUnavailableException {
@ -955,6 +962,19 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
String time = configs.get("storage.cleanup.interval"); String time = configs.get("storage.cleanup.interval");
_storageCleanupInterval = NumbersUtil.parseInt(time, 86400); _storageCleanupInterval = NumbersUtil.parseInt(time, 86400);
String storageUsedThreshold = configDao.getValue(Config.StorageCapacityDisableThreshold.key());
if (storageUsedThreshold != null) {
_storageUsedThreshold = Double.parseDouble(storageUsedThreshold);
}
String storageAllocatedThreshold = configDao.getValue(Config.StorageAllocatedCapacityDisableThreshold.key());
if (storageAllocatedThreshold != null) {
_storageAllocatedThreshold = Double.parseDouble(storageAllocatedThreshold);
}
String globalStorageOverprovisioningFactor = configs.get("storage.overprovisioning.factor");
_storageOverprovisioningFactor = new BigDecimal(NumbersUtil.parseFloat(globalStorageOverprovisioningFactor, 2.0f));
s_logger.info("Storage cleanup enabled: " + _storageCleanupEnabled + ", interval: " + _storageCleanupInterval + ", template cleanup enabled: " + _templateCleanupEnabled); s_logger.info("Storage cleanup enabled: " + _storageCleanupEnabled + ", interval: " + _storageCleanupInterval + ", template cleanup enabled: " + _templateCleanupEnabled);
String workers = configs.get("expunge.workers"); String workers = configs.get("expunge.workers");
@ -1257,10 +1277,10 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
if (uriPath == null) { if (uriPath == null) {
throw new InvalidParameterValueException("host or path is null, should be sharedmountpoint://localhost/path"); throw new InvalidParameterValueException("host or path is null, should be sharedmountpoint://localhost/path");
} }
} else if (uri.getScheme().equalsIgnoreCase("clvm")) { } else if (uri.getScheme().equalsIgnoreCase("rbd")) {
String uriPath = uri.getPath(); String uriPath = uri.getPath();
if (uriPath == null) { if (uriPath == null) {
throw new InvalidParameterValueException("host or path is null, should be clvm://localhost/path"); throw new InvalidParameterValueException("host or path is null, should be rbd://hostname/pool");
} }
} }
} catch (URISyntaxException e) { } catch (URISyntaxException e) {
@ -1283,6 +1303,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
String scheme = uri.getScheme(); String scheme = uri.getScheme();
String storageHost = uri.getHost(); String storageHost = uri.getHost();
String hostPath = uri.getPath(); String hostPath = uri.getPath();
String userInfo = uri.getUserInfo();
int port = uri.getPort(); int port = uri.getPort();
StoragePoolVO pool = null; StoragePoolVO pool = null;
if (s_logger.isDebugEnabled()) { if (s_logger.isDebugEnabled()) {
@ -1303,6 +1324,11 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
pool = new StoragePoolVO(StoragePoolType.Filesystem, "localhost", 0, hostPath); pool = new StoragePoolVO(StoragePoolType.Filesystem, "localhost", 0, hostPath);
} else if (scheme.equalsIgnoreCase("sharedMountPoint")) { } else if (scheme.equalsIgnoreCase("sharedMountPoint")) {
pool = new StoragePoolVO(StoragePoolType.SharedMountPoint, storageHost, 0, hostPath); pool = new StoragePoolVO(StoragePoolType.SharedMountPoint, storageHost, 0, hostPath);
} else if (scheme.equalsIgnoreCase("rbd")) {
if (port == -1) {
port = 6789;
}
pool = new StoragePoolVO(StoragePoolType.RBD, storageHost, port, hostPath.replaceFirst("/", ""), userInfo);
} else if (scheme.equalsIgnoreCase("PreSetup")) { } else if (scheme.equalsIgnoreCase("PreSetup")) {
pool = new StoragePoolVO(StoragePoolType.PreSetup, storageHost, 0, hostPath); pool = new StoragePoolVO(StoragePoolType.PreSetup, storageHost, 0, hostPath);
} else if (scheme.equalsIgnoreCase("iscsi")) { } else if (scheme.equalsIgnoreCase("iscsi")) {
@ -1601,7 +1627,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
s_logger.debug("creating pool " + pool.getName() + " on host " + hostId); s_logger.debug("creating pool " + pool.getName() + " on host " + hostId);
if (pool.getPoolType() != StoragePoolType.NetworkFilesystem && pool.getPoolType() != StoragePoolType.Filesystem && pool.getPoolType() != StoragePoolType.IscsiLUN if (pool.getPoolType() != StoragePoolType.NetworkFilesystem && pool.getPoolType() != StoragePoolType.Filesystem && pool.getPoolType() != StoragePoolType.IscsiLUN
&& pool.getPoolType() != StoragePoolType.Iscsi && pool.getPoolType() != StoragePoolType.VMFS && pool.getPoolType() != StoragePoolType.SharedMountPoint && pool.getPoolType() != StoragePoolType.Iscsi && pool.getPoolType() != StoragePoolType.VMFS && pool.getPoolType() != StoragePoolType.SharedMountPoint
&& pool.getPoolType() != StoragePoolType.PreSetup && pool.getPoolType() != StoragePoolType.OCFS2) { && pool.getPoolType() != StoragePoolType.PreSetup && pool.getPoolType() != StoragePoolType.OCFS2 && pool.getPoolType() != StoragePoolType.RBD) {
s_logger.warn(" Doesn't support storage pool type " + pool.getPoolType()); s_logger.warn(" Doesn't support storage pool type " + pool.getPoolType());
return false; return false;
} }
@ -3906,5 +3932,81 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
return HypervisorType.None; return HypervisorType.None;
} }
} }
private boolean checkUsagedSpace(StoragePool pool){
StatsCollector sc = StatsCollector.getInstance();
if (sc != null) {
long totalSize = pool.getCapacityBytes();
StorageStats stats = sc.getStoragePoolStats(pool.getId());
if(stats == null){
stats = sc.getStorageStats(pool.getId());
}
if (stats != null) {
double usedPercentage = ((double)stats.getByteUsed() / (double)totalSize);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Checking pool " + pool.getId() + " for storage, totalSize: " + pool.getCapacityBytes() + ", usedBytes: " + stats.getByteUsed() + ", usedPct: " + usedPercentage + ", disable threshold: " + _storageUsedThreshold);
}
if (usedPercentage >= _storageUsedThreshold) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Insufficient space on pool: " + pool.getId() + " since its usage percentage: " +usedPercentage + " has crossed the pool.storage.capacity.disablethreshold: " + _storageUsedThreshold);
}
return false;
}
}
return true;
}
return false;
}
@Override
public boolean storagePoolHasEnoughSpace(List<Volume> volumes, StoragePool pool) {
if(volumes == null || volumes.isEmpty())
return false;
if(!checkUsagedSpace(pool))
return false;
// allocated space includes template of specified volume
StoragePoolVO poolVO = _storagePoolDao.findById(pool.getId());
long allocatedSizeWithtemplate = _capacityMgr.getAllocatedPoolCapacity(poolVO, null);
long totalAskingSize = 0;
for (Volume volume : volumes) {
if(volume.getTemplateId()!=null){
VMTemplateVO tmpl = _templateDao.findById(volume.getTemplateId());
if (tmpl.getFormat() != ImageFormat.ISO){
allocatedSizeWithtemplate = _capacityMgr.getAllocatedPoolCapacity(poolVO, tmpl);
}
}
if(volume.getState() != Volume.State.Ready)
totalAskingSize = totalAskingSize + volume.getSize();
}
long totalOverProvCapacity;
if (pool.getPoolType() == StoragePoolType.NetworkFilesystem) {
totalOverProvCapacity = _storageOverprovisioningFactor.multiply(new BigDecimal(pool.getCapacityBytes())).longValue();// All this for the inaccuracy of floats for big number multiplication.
}else {
totalOverProvCapacity = pool.getCapacityBytes();
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("Checking pool: " + pool.getId() + " for volume allocation " + volumes.toString() + ", maxSize : " + totalOverProvCapacity + ", totalAllocatedSize : " + allocatedSizeWithtemplate + ", askingSize : " + totalAskingSize + ", allocated disable threshold: " + _storageAllocatedThreshold);
}
double usedPercentage = (allocatedSizeWithtemplate + totalAskingSize) / (double)(totalOverProvCapacity);
if (usedPercentage > _storageAllocatedThreshold){
if (s_logger.isDebugEnabled()) {
s_logger.debug("Insufficient un-allocated capacity on: " + pool.getId() + " for volume allocation: " + volumes.toString() + " since its allocated percentage: " +usedPercentage + " has crossed the allocated pool.storage.allocated.capacity.disablethreshold: " + _storageAllocatedThreshold + ", skipping this pool");
}
return false;
}
if (totalOverProvCapacity < (allocatedSizeWithtemplate + totalAskingSize)) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Insufficient un-allocated capacity on: " + pool.getId() + " for volume allocation: " + volumes.toString() + ", not enough storage, maxSize : " + totalOverProvCapacity + ", totalAllocatedSize : " + allocatedSizeWithtemplate + ", askingSize : " + totalAskingSize);
}
return false;
}
return true;
}
} }

View File

@ -17,6 +17,7 @@
package com.cloud.storage.allocator; package com.cloud.storage.allocator;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
@ -27,7 +28,6 @@ import javax.naming.ConfigurationException;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import com.cloud.capacity.CapacityManager; import com.cloud.capacity.CapacityManager;
import com.cloud.configuration.Config;
import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.ClusterVO; import com.cloud.dc.ClusterVO;
import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.ClusterDao;
@ -41,13 +41,11 @@ import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolStatus; import com.cloud.storage.StoragePoolStatus;
import com.cloud.storage.StoragePoolVO; import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.StorageStats;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateStoragePoolVO; import com.cloud.storage.VMTemplateStoragePoolVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.VMTemplateSwiftVO;
import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.Volume.Type; import com.cloud.storage.Volume.Type;
import com.cloud.storage.dao.StoragePoolDao; import com.cloud.storage.dao.StoragePoolDao;
import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.storage.dao.StoragePoolHostDao;
@ -58,7 +56,6 @@ import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.swift.SwiftManager; import com.cloud.storage.swift.SwiftManager;
import com.cloud.template.TemplateManager; import com.cloud.template.TemplateManager;
import com.cloud.utils.NumbersUtil; import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.component.AdapterBase; import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.Inject; import com.cloud.utils.component.Inject;
import com.cloud.vm.DiskProfile; import com.cloud.vm.DiskProfile;
@ -83,8 +80,6 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement
long _extraBytesPerVolume = 0; long _extraBytesPerVolume = 0;
Random _rand; Random _rand;
boolean _dontMatter; boolean _dontMatter;
double _storageUsedThreshold = 1.0d;
double _storageAllocatedThreshold = 1.0d;
@Override @Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException { public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
@ -97,17 +92,6 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement
_extraBytesPerVolume = 0; _extraBytesPerVolume = 0;
String storageUsedThreshold = _configDao.getValue(Config.StorageCapacityDisableThreshold.key());
if (storageUsedThreshold != null) {
_storageUsedThreshold = Double.parseDouble(storageUsedThreshold);
}
String storageAllocatedThreshold = _configDao.getValue(Config.StorageAllocatedCapacityDisableThreshold.key());
if (storageAllocatedThreshold != null) {
_storageAllocatedThreshold = Double.parseDouble(storageAllocatedThreshold);
}
_rand = new Random(System.currentTimeMillis()); _rand = new Random(System.currentTimeMillis());
_dontMatter = Boolean.parseBoolean(configs.get("storage.overwrite.provisioning")); _dontMatter = Boolean.parseBoolean(configs.get("storage.overwrite.provisioning"));
@ -192,60 +176,15 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement
return false; return false;
} }
// check the used size against the total size, skip this host if it's greater than the configured
// capacity check "storage.capacity.threshold"
if (sc != null) {
long totalSize = pool.getCapacityBytes();
StorageStats stats = sc.getStoragePoolStats(pool.getId());
if(stats == null){
stats = sc.getStorageStats(pool.getId());
}
if (stats != null) {
double usedPercentage = ((double)stats.getByteUsed() / (double)totalSize);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Attempting to look for pool " + pool.getId() + " for storage, totalSize: " + pool.getCapacityBytes() + ", usedBytes: " + stats.getByteUsed() + ", usedPct: " + usedPercentage + ", disable threshold: " + _storageUsedThreshold);
}
if (usedPercentage >= _storageUsedThreshold) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Cannot allocate this pool " + pool.getId() + " for storage since its usage percentage: " +usedPercentage + " has crossed the pool.storage.capacity.disablethreshold: " + _storageUsedThreshold + ", skipping this pool");
}
return false;
}
}
}
long totalAllocatedSize = _capacityMgr.getAllocatedPoolCapacity(pool, null);
long askingSize = dskCh.getSize();
long totalOverProvCapacity;
if (pool.getPoolType() == StoragePoolType.NetworkFilesystem) {
totalOverProvCapacity = _storageOverprovisioningFactor.multiply(new BigDecimal(pool.getCapacityBytes())).longValue();// All this for the inaccuracy of floats for big number multiplication.
}else {
totalOverProvCapacity = pool.getCapacityBytes();
}
if (s_logger.isDebugEnabled()) { // check capacity
s_logger.debug("Attempting to look for pool " + pool.getId() + " for storage, maxSize : " + totalOverProvCapacity + ", totalAllocatedSize : " + totalAllocatedSize + ", askingSize : " + askingSize + ", allocated disable threshold: " + _storageAllocatedThreshold); Volume volume = _volumeDao.findById(dskCh.getVolumeId());
} List<Volume> requestVolumes = new ArrayList<Volume>();
requestVolumes.add(volume);
double usedPercentage = (totalAllocatedSize + askingSize) / (double)(totalOverProvCapacity); return _storageMgr.storagePoolHasEnoughSpace(requestVolumes, pool);
if (usedPercentage > _storageAllocatedThreshold){
if (s_logger.isDebugEnabled()) {
s_logger.debug("Cannot allocate this pool " + pool.getId() + " for storage since its allocated percentage: " +usedPercentage + " has crossed the allocated pool.storage.allocated.capacity.disablethreshold: " + _storageAllocatedThreshold + ", skipping this pool");
}
return false;
}
if (totalOverProvCapacity < (totalAllocatedSize + askingSize)) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Cannot allocate this pool " + pool.getId() + " for storage, not enough storage, maxSize : " + totalOverProvCapacity + ", totalAllocatedSize : " + totalAllocatedSize + ", askingSize : " + askingSize);
}
return false;
}
return true;
} }
@Override @Override
public String chooseStorageIp(VirtualMachine vm, Host host, Host storage) { public String chooseStorageIp(VirtualMachine vm, Host host, Host storage) {

View File

@ -31,18 +31,25 @@ import org.apache.log4j.Logger;
import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlan;
import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.server.StatsCollector; import com.cloud.server.StatsCollector;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolVO; import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.user.Account; import com.cloud.user.Account;
import com.cloud.vm.DiskProfile; import com.cloud.vm.DiskProfile;
import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.VirtualMachineProfile;
import com.cloud.utils.component.Inject;
@Local(value=StoragePoolAllocator.class) @Local(value=StoragePoolAllocator.class)
public class FirstFitStoragePoolAllocator extends AbstractStoragePoolAllocator { public class FirstFitStoragePoolAllocator extends AbstractStoragePoolAllocator {
private static final Logger s_logger = Logger.getLogger(FirstFitStoragePoolAllocator.class); private static final Logger s_logger = Logger.getLogger(FirstFitStoragePoolAllocator.class);
protected String _allocationAlgorithm = "random"; protected String _allocationAlgorithm = "random";
@Inject
DiskOfferingDao _diskOfferingDao;
@Override @Override
public boolean allocatorIsCorrectType(DiskProfile dskCh) { public boolean allocatorIsCorrectType(DiskProfile dskCh) {
@ -97,10 +104,16 @@ public class FirstFitStoragePoolAllocator extends AbstractStoragePoolAllocator {
s_logger.debug("FirstFitStoragePoolAllocator has " + pools.size() + " pools to check for allocation"); s_logger.debug("FirstFitStoragePoolAllocator has " + pools.size() + " pools to check for allocation");
} }
DiskOfferingVO diskOffering = _diskOfferingDao.findById(dskCh.getDiskOfferingId());
for (StoragePoolVO pool: pools) { for (StoragePoolVO pool: pools) {
if(suitablePools.size() == returnUpTo){ if(suitablePools.size() == returnUpTo){
break; break;
} }
if (diskOffering.getSystemUse() && pool.getPoolType() == StoragePoolType.RBD) {
s_logger.debug("Skipping RBD pool " + pool.getName() + " as a suitable pool. RBD is not supported for System VM's");
continue;
}
if (checkPool(avoid, pool, dskCh, template, null, sc, plan)) { if (checkPool(avoid, pool, dskCh, template, null, sc, plan)) {
suitablePools.add(pool); suitablePools.add(pool);
} }

View File

@ -63,6 +63,7 @@ public interface VMTemplateDao extends GenericDao<VMTemplateVO, Long> {
public List<VMTemplateVO> listByHypervisorType(List<HypervisorType> hyperTypes); public List<VMTemplateVO> listByHypervisorType(List<HypervisorType> hyperTypes);
public List<VMTemplateVO> publicIsoSearch(Boolean bootable, boolean listRemoved, Map<String, String> tags); public List<VMTemplateVO> publicIsoSearch(Boolean bootable, boolean listRemoved, Map<String, String> tags);
public List<VMTemplateVO> userIsoSearch(boolean listRemoved);
VMTemplateVO findSystemVMTemplate(long zoneId); VMTemplateVO findSystemVMTemplate(long zoneId);
VMTemplateVO findSystemVMTemplate(long zoneId, HypervisorType hType); VMTemplateVO findSystemVMTemplate(long zoneId, HypervisorType hType);

View File

@ -84,7 +84,6 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
DomainDao _domainDao; DomainDao _domainDao;
@Inject @Inject
DataCenterDao _dcDao; DataCenterDao _dcDao;
private final String SELECT_TEMPLATE_HOST_REF = "SELECT t.id, h.data_center_id, t.unique_name, t.name, t.public, t.featured, t.type, t.hvm, t.bits, t.url, t.format, t.created, t.account_id, " + private final String SELECT_TEMPLATE_HOST_REF = "SELECT t.id, h.data_center_id, t.unique_name, t.name, t.public, t.featured, t.type, t.hvm, t.bits, t.url, t.format, t.created, t.account_id, " +
"t.checksum, t.display_text, t.enable_password, t.guest_os_id, t.bootable, t.prepopulate, t.cross_zones, t.hypervisor_type FROM vm_template t"; "t.checksum, t.display_text, t.enable_password, t.guest_os_id, t.bootable, t.prepopulate, t.cross_zones, t.hypervisor_type FROM vm_template t";
@ -93,7 +92,6 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
private final String SELECT_TEMPLATE_SWIFT_REF = "SELECT t.id, t.unique_name, t.name, t.public, t.featured, t.type, t.hvm, t.bits, t.url, t.format, t.created, t.account_id, " private final String SELECT_TEMPLATE_SWIFT_REF = "SELECT t.id, t.unique_name, t.name, t.public, t.featured, t.type, t.hvm, t.bits, t.url, t.format, t.created, t.account_id, "
+ "t.checksum, t.display_text, t.enable_password, t.guest_os_id, t.bootable, t.prepopulate, t.cross_zones, t.hypervisor_type FROM vm_template t"; + "t.checksum, t.display_text, t.enable_password, t.guest_os_id, t.bootable, t.prepopulate, t.cross_zones, t.hypervisor_type FROM vm_template t";
protected SearchBuilder<VMTemplateVO> TemplateNameSearch; protected SearchBuilder<VMTemplateVO> TemplateNameSearch;
protected SearchBuilder<VMTemplateVO> UniqueNameSearch; protected SearchBuilder<VMTemplateVO> UniqueNameSearch;
protected SearchBuilder<VMTemplateVO> tmpltTypeSearch; protected SearchBuilder<VMTemplateVO> tmpltTypeSearch;
@ -106,6 +104,7 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
private SearchBuilder<VMTemplateVO> PublicSearch; private SearchBuilder<VMTemplateVO> PublicSearch;
private SearchBuilder<VMTemplateVO> NameAccountIdSearch; private SearchBuilder<VMTemplateVO> NameAccountIdSearch;
private SearchBuilder<VMTemplateVO> PublicIsoSearch; private SearchBuilder<VMTemplateVO> PublicIsoSearch;
private SearchBuilder<VMTemplateVO> UserIsoSearch;
private GenericSearchBuilder<VMTemplateVO, Long> CountTemplatesByAccount; private GenericSearchBuilder<VMTemplateVO, Long> CountTemplatesByAccount;
ResourceTagsDaoImpl _tagsDao = ComponentLocator.inject(ResourceTagsDaoImpl.class); ResourceTagsDaoImpl _tagsDao = ComponentLocator.inject(ResourceTagsDaoImpl.class);
@ -189,6 +188,22 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
return listBy(sc); return listBy(sc);
} }
@Override
public List<VMTemplateVO> userIsoSearch(boolean listRemoved){
SearchBuilder<VMTemplateVO> sb = null;
sb = UserIsoSearch;
SearchCriteria<VMTemplateVO> sc = sb.create();
sc.setParameters("format", Storage.ImageFormat.ISO);
sc.setParameters("type", TemplateType.USER.toString());
if (!listRemoved) {
sc.setParameters("removed", (Object)null);
}
return listBy(sc);
}
@Override @Override
public List<VMTemplateVO> listAllSystemVMTemplates() { public List<VMTemplateVO> listAllSystemVMTemplates() {
SearchCriteria<VMTemplateVO> sc = tmpltTypeSearch.create(); SearchCriteria<VMTemplateVO> sc = tmpltTypeSearch.create();
@ -298,7 +313,12 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
PublicIsoSearch.and("type", PublicIsoSearch.entity().getTemplateType(), SearchCriteria.Op.EQ); PublicIsoSearch.and("type", PublicIsoSearch.entity().getTemplateType(), SearchCriteria.Op.EQ);
PublicIsoSearch.and("bootable", PublicIsoSearch.entity().isBootable(), SearchCriteria.Op.EQ); PublicIsoSearch.and("bootable", PublicIsoSearch.entity().isBootable(), SearchCriteria.Op.EQ);
PublicIsoSearch.and("removed", PublicIsoSearch.entity().getRemoved(), SearchCriteria.Op.EQ); PublicIsoSearch.and("removed", PublicIsoSearch.entity().getRemoved(), SearchCriteria.Op.EQ);
UserIsoSearch = createSearchBuilder();
UserIsoSearch.and("format", UserIsoSearch.entity().getFormat(), SearchCriteria.Op.EQ);
UserIsoSearch.and("type", UserIsoSearch.entity().getTemplateType(), SearchCriteria.Op.EQ);
UserIsoSearch.and("removed", UserIsoSearch.entity().getRemoved(), SearchCriteria.Op.EQ);
tmpltTypeHyperSearch = createSearchBuilder(); tmpltTypeHyperSearch = createSearchBuilder();
tmpltTypeHyperSearch.and("templateType", tmpltTypeHyperSearch.entity().getTemplateType(), SearchCriteria.Op.EQ); tmpltTypeHyperSearch.and("templateType", tmpltTypeHyperSearch.entity().getTemplateType(), SearchCriteria.Op.EQ);
SearchBuilder<HostVO> hostHyperSearch = _hostDao.createSearchBuilder(); SearchBuilder<HostVO> hostHyperSearch = _hostDao.createSearchBuilder();
@ -648,28 +668,44 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
pstmt = txn.prepareStatement(sql); pstmt = txn.prepareStatement(sql);
rs = pstmt.executeQuery(); rs = pstmt.executeQuery();
while (rs.next()) { while (rs.next()) {
Pair<Long, Long> templateZonePair = new Pair<Long, Long>(rs.getLong(1), rs.getLong(2)); Pair<Long, Long> templateZonePair = new Pair<Long, Long>(rs.getLong(1), rs.getLong(2));
templateZonePairList.add(templateZonePair); templateZonePairList.add(templateZonePair);
} }
//for now, defaulting pageSize to a large val if null; may need to revisit post 2.2RC2 //for now, defaulting pageSize to a large val if null; may need to revisit post 2.2RC2
if(isIso && templateZonePairList.size() < (pageSize != null ? pageSize : 500) if(isIso && templateZonePairList.size() < (pageSize != null ? pageSize : 500)
&& templateFilter != TemplateFilter.community && templateFilter != TemplateFilter.community
&& !(templateFilter == TemplateFilter.self && !BaseCmd.isRootAdmin(caller.getType())) ){ //evaluates to true If root admin and filter=self && !(templateFilter == TemplateFilter.self && !BaseCmd.isRootAdmin(caller.getType())) ){ //evaluates to true If root admin and filter=self
List<VMTemplateVO> publicIsos = publicIsoSearch(bootable, false, tags);
for( int i=0; i < publicIsos.size(); i++){ List<VMTemplateVO> publicIsos = publicIsoSearch(bootable, false, tags);
if (keyword != null && publicIsos.get(i).getName().contains(keyword)) { List<VMTemplateVO> userIsos = userIsoSearch(false);
templateZonePairList.add(new Pair<Long,Long>(publicIsos.get(i).getId(), null));
continue; //Listing the ISOs according to the page size.Restricting the total no. of ISOs on a page
} else if (name != null && publicIsos.get(i).getName().contains(name)) { //to be less than or equal to the pageSize parameter
templateZonePairList.add(new Pair<Long,Long>(publicIsos.get(i).getId(), null));
continue; int i=0;
}else if (keyword == null && name == null){
templateZonePairList.add(new Pair<Long,Long>(publicIsos.get(i).getId(), null)); if (startIndex > userIsos.size()) {
i=(int) (startIndex - userIsos.size());
}
for (; i < publicIsos.size(); i++) {
if(templateZonePairList.size() >= pageSize){
break;
} else {
if (keyword != null && publicIsos.get(i).getName().contains(keyword)) {
templateZonePairList.add(new Pair<Long,Long>(publicIsos.get(i).getId(), null));
continue;
} else if (name != null && publicIsos.get(i).getName().contains(name)) {
templateZonePairList.add(new Pair<Long,Long>(publicIsos.get(i).getId(), null));
continue;
} else if (keyword == null && name == null){
templateZonePairList.add(new Pair<Long,Long>(publicIsos.get(i).getId(), null));
}
}
} }
} }
}
} catch (Exception e) { } catch (Exception e) {
s_logger.warn("Error listing templates", e); s_logger.warn("Error listing templates", e);
} finally { } finally {

View File

@ -1477,4 +1477,9 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
// TODO Auto-generated method stub // TODO Auto-generated method stub
return false; return false;
} }
@Override
public void prepareStop(VirtualMachineProfile<SecondaryStorageVmVO> profile) {
}
} }

View File

@ -79,6 +79,7 @@ import com.cloud.storage.SnapshotPolicyVO;
import com.cloud.storage.SnapshotScheduleVO; import com.cloud.storage.SnapshotScheduleVO;
import com.cloud.storage.SnapshotVO; import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Storage; import com.cloud.storage.Storage;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StorageManager; import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolVO; import com.cloud.storage.StoragePoolVO;
@ -298,6 +299,13 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
} }
} }
StoragePoolVO srcPool = _storagePoolDao.findById(volume.getPoolId()); StoragePoolVO srcPool = _storagePoolDao.findById(volume.getPoolId());
// RBD volumes do not support snapshotting in the way CloudStack does it.
// For now we leave the snapshot feature disabled for RBD volumes
if (srcPool.getPoolType() == StoragePoolType.RBD) {
throw new CloudRuntimeException("RBD volumes do not support snapshotting");
}
ManageSnapshotCommand cmd = new ManageSnapshotCommand(snapshotId, volume.getPath(), srcPool, preSnapshotPath, snapshot.getName(), vmName); ManageSnapshotCommand cmd = new ManageSnapshotCommand(snapshotId, volume.getPath(), srcPool, preSnapshotPath, snapshot.getName(), vmName);
ManageSnapshotAnswer answer = (ManageSnapshotAnswer) sendToPool(volume, cmd); ManageSnapshotAnswer answer = (ManageSnapshotAnswer) sendToPool(volume, cmd);

View File

@ -55,6 +55,7 @@ import com.cloud.upgrade.dao.Upgrade229to2210;
import com.cloud.upgrade.dao.Upgrade301to302; import com.cloud.upgrade.dao.Upgrade301to302;
import com.cloud.upgrade.dao.Upgrade302to303; import com.cloud.upgrade.dao.Upgrade302to303;
import com.cloud.upgrade.dao.Upgrade30to301; import com.cloud.upgrade.dao.Upgrade30to301;
import com.cloud.upgrade.dao.Upgrade303to40;
import com.cloud.upgrade.dao.UpgradeSnapshot217to224; import com.cloud.upgrade.dao.UpgradeSnapshot217to224;
import com.cloud.upgrade.dao.UpgradeSnapshot223to224; import com.cloud.upgrade.dao.UpgradeSnapshot223to224;
import com.cloud.upgrade.dao.VersionDao; import com.cloud.upgrade.dao.VersionDao;
@ -152,11 +153,13 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker {
_upgradeMap.put("2.2.14", new DbUpgrade[] { new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), _upgradeMap.put("2.2.14", new DbUpgrade[] { new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(),
new Upgrade302to303() }); new Upgrade302to303() });
_upgradeMap.put("3.0.0", new DbUpgrade[] { new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to303() }); _upgradeMap.put("3.0.0", new DbUpgrade[] { new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to303(), new Upgrade303to40() });
_upgradeMap.put("3.0.1", new DbUpgrade[] { new Upgrade301to302(), new Upgrade302to303() }); _upgradeMap.put("3.0.1", new DbUpgrade[] { new Upgrade301to302(), new Upgrade302to303(), new Upgrade303to40() });
_upgradeMap.put("3.0.2", new DbUpgrade[] { new Upgrade302to303() }); _upgradeMap.put("3.0.2", new DbUpgrade[] { new Upgrade302to303(), new Upgrade303to40() });
_upgradeMap.put("3.0.3", new DbUpgrade[] { new Upgrade303to40() });
} }
protected void runScript(Connection conn, File file) { protected void runScript(Connection conn, File file) {

View File

@ -14,17 +14,6 @@
// KIND, either express or implied. See the License for the // KIND, either express or implied. See the License for the
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
/*Copyright 2012 Citrix Systems, Inc. Licensed under the
Apache License, Version 2.0 (the "License"); you may not use this
file except in compliance with the License. Citrix Systems, Inc.
reserves all rights not expressly granted by the License.
You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.*/
package com.cloud.upgrade.dao; package com.cloud.upgrade.dao;

View File

@ -0,0 +1,67 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.upgrade.dao;
/**
* @author Alena Prokharchyk
*/
import java.io.File;
import java.sql.Connection;
import org.apache.log4j.Logger;
//
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.Script;
public class Upgrade303to40 implements DbUpgrade {
final static Logger s_logger = Logger.getLogger(Upgrade303to40.class);
@Override
public String[] getUpgradableVersionRange() {
return new String[] { "3.0.3", "4.0.0" };
}
@Override
public String getUpgradedVersion() {
return "4.0.0";
}
@Override
public boolean supportsRollingUpgrade() {
return false;
}
@Override
public File[] getPrepareScripts() {
String script = Script.findScript("", "db/schema-303to40.sql");
if (script == null) {
throw new CloudRuntimeException("Unable to find db/schema-303to40.sql");
}
return new File[] { new File(script) };
}
@Override
public void performDataMigration(Connection conn) {
}
@Override
public File[] getCleanupScripts() {
return null;
}
}

View File

@ -3694,5 +3694,9 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
//not supported //not supported
throw new UnsupportedOperationException("Unplug nic is not supported for vm of type " + vm.getType()); throw new UnsupportedOperationException("Unplug nic is not supported for vm of type " + vm.getType());
} }
@Override
public void prepareStop(VirtualMachineProfile<UserVmVO> profile) {
}
} }

View File

@ -82,6 +82,7 @@ public interface VirtualMachineGuru<T extends VirtualMachine> {
Long convertToId(String vmName); Long convertToId(String vmName);
/** /**
<<<<<<< HEAD
* Prepare for a nic to be plugged into the network. * Prepare for a nic to be plugged into the network.
* @param network * @param network
* @param nic * @param nic
@ -110,4 +111,11 @@ public interface VirtualMachineGuru<T extends VirtualMachine> {
*/ */
boolean unplugNic(Network network, NicTO nic, VirtualMachineTO vm, boolean unplugNic(Network network, NicTO nic, VirtualMachineTO vm,
ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException; ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException;
/**
* Prepare Vm for Stop
* @param profile
* @return
*/
void prepareStop(VirtualMachineProfile<T> profile);
} }

View File

@ -1074,11 +1074,10 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
if (vm.getState() != State.Stopping) { if (vm.getState() != State.Stopping) {
throw new CloudRuntimeException("We cannot proceed with stop VM " + vm + " since it is not in 'Stopping' state, current state: " + vm.getState()); throw new CloudRuntimeException("We cannot proceed with stop VM " + vm + " since it is not in 'Stopping' state, current state: " + vm.getState());
} }
String routerPrivateIp = null;
if (vm.getType() == VirtualMachine.Type.DomainRouter) { vmGuru.prepareStop(profile);
routerPrivateIp = vm.getPrivateIpAddress();
} StopCommand stop = new StopCommand(vm, vm.getInstanceName(), null);
StopCommand stop = new StopCommand(vm, vm.getInstanceName(), null, routerPrivateIp);
boolean stopped = false; boolean stopped = false;
StopAnswer answer = null; StopAnswer answer = null;
try { try {

View File

@ -1487,6 +1487,7 @@ CREATE TABLE `cloud`.`storage_pool` (
`available_bytes` bigint unsigned, `available_bytes` bigint unsigned,
`capacity_bytes` bigint unsigned, `capacity_bytes` bigint unsigned,
`host_address` varchar(255) NOT NULL COMMENT 'FQDN or IP of storage server', `host_address` varchar(255) NOT NULL COMMENT 'FQDN or IP of storage server',
`user_info` varchar(255) NULL COMMENT 'Authorization information for the storage pool. Used by network filesystems',
`path` varchar(255) NOT NULL COMMENT 'Filesystem path that is shared', `path` varchar(255) NOT NULL COMMENT 'Filesystem path that is shared',
`created` datetime COMMENT 'date the pool created', `created` datetime COMMENT 'date the pool created',
`removed` datetime COMMENT 'date removed if not null', `removed` datetime COMMENT 'date removed if not null',

View File

@ -0,0 +1,63 @@
-- Licensed to the Apache Software Foundation (ASF) under one
-- or more contributor license agreements. See the NOTICE file
-- distributed with this work for additional information
-- regarding copyright ownership. The ASF licenses this file
-- to you under the Apache License, Version 2.0 (the
-- "License"); you may not use this file except in compliance
-- with the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing,
-- software distributed under the License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-- KIND, either express or implied. See the License for the
-- specific language governing permissions and limitations
-- under the License.
--;
-- Schema upgrade from 3.0.3 to 4.0.0;
--;
# RBD Primary Storage pool support (commit: 406fd95d87bfcdbb282d65589ab1fb6e9fd0018a)
ALTER TABLE `storage_pool` ADD `user_info` VARCHAR( 255 ) NULL COMMENT 'Authorization information for the storage pool. Used by network filesystems' AFTER `host_address`;
# Resource tags (commit: 62d45b9670520a1ee8b520509393d4258c689b50)
CREATE TABLE `cloud`.`resource_tags` (
`id` bigint unsigned NOT NULL auto_increment COMMENT 'id',
`uuid` varchar(40),
`key` varchar(255),
`value` varchar(255),
`resource_id` bigint unsigned NOT NULL,
`resource_uuid` varchar(40),
`resource_type` varchar(255),
`customer` varchar(255),
`domain_id` bigint unsigned NOT NULL COMMENT 'foreign key to domain id',
`account_id` bigint unsigned NOT NULL COMMENT 'owner of this network',
PRIMARY KEY (`id`),
CONSTRAINT `fk_tags__account_id` FOREIGN KEY(`account_id`) REFERENCES `account`(`id`),
CONSTRAINT `fk_tags__domain_id` FOREIGN KEY(`domain_id`) REFERENCES `domain`(`id`),
UNIQUE `i_tags__resource_id__resource_type__key`(`resource_id`, `resource_type`, `key`),
CONSTRAINT `uc_resource_tags__uuid` UNIQUE (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
# Nicira Integration (commit: 79c7da07abd4294f150851aa0c2d06a28564c5a9)
CREATE TABLE `cloud`.`external_nicira_nvp_devices` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`uuid` varchar(255) UNIQUE,
`physical_network_id` bigint unsigned NOT NULL COMMENT 'id of the physical network in to which nicira nvp device is added',
`provider_name` varchar(255) NOT NULL COMMENT 'Service Provider name corresponding to this nicira nvp device',
`device_name` varchar(255) NOT NULL COMMENT 'name of the nicira nvp device',
`host_id` bigint unsigned NOT NULL COMMENT 'host id coresponding to the external nicira nvp device',
PRIMARY KEY (`id`),
CONSTRAINT `fk_external_nicira_nvp_devices__host_id` FOREIGN KEY (`host_id`) REFERENCES `host`(`id`) ON DELETE CASCADE,
CONSTRAINT `fk_external_nicira_nvp_devices__physical_network_id` FOREIGN KEY (`physical_network_id`) REFERENCES `physical_network`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `cloud`.`nicira_nvp_nic_map` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`logicalswitch` varchar(255) NOT NULL COMMENT 'nicira uuid of logical switch this port is provisioned on',
`logicalswitchport` varchar(255) UNIQUE COMMENT 'nicira uuid of this logical switch port',
`nic` varchar(255) UNIQUE COMMENT 'cloudstack uuid of the nic connected to this logical switch port',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

6
tools/devcloud/README Normal file
View File

@ -0,0 +1,6 @@
This folder contains various scripts used to build the devcloud image.
Folders:
puppet - puppet conf files and module directories for the various build phases
vagrant - basic vagrant configuration for a devcloud box (and a puppet manifest to help configure the system to be a valid vagrant box)
ubuntu_install - ubuntu installation / initial configuration

View File

@ -0,0 +1,12 @@
To use:
Preconfiguration phase -
- [setup your box in vagrant and place the contents of tools/devcloud/puppet into the box's folder]
- vagrant up; vagrant ssh
- sudo bash
- ln -s /vagrant/puppet-devcloudinitial /etc/puppet/modules/puppet-devcloudinitial
- cd /vagrant
- puppet apply --fsconfig fileserver.conf --debug --verbose -e "include puppet-devcloudinitial"
Postconfiguration phase -
TODO

View File

@ -0,0 +1,8 @@
name 'puppet-devcloudinitial'
version '0.0.1'
source ''
author 'Apache Software Foundation'
license 'Apache 2.0'
summary 'CloudStack DevCloud initial configuration module'
description 'Installation and configuration of all prequisites for building a DevCloud image.'
project_page 'http://cloudstack.org'

View File

@ -0,0 +1,34 @@
# If you change this file, run 'update-grub' afterwards to update
# /boot/grub/grub.cfg.
# For full documentation of the options in this file, see:
# info -f grub -n 'Simple configuration'
GRUB_DEFAULT=0
#GRUB_HIDDEN_TIMEOUT=0
GRUB_HIDDEN_TIMEOUT_QUIET=true
GRUB_TIMEOUT=2
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT=""
GRUB_CMDLINE_LINUX=""
# Uncomment to enable BadRAM filtering, modify to suit your needs
# This works with Linux (no patch required) and with any kernel that obtains
# the memory map information from GRUB (GNU Mach, kernel of FreeBSD ...)
#GRUB_BADRAM="0x01234567,0xfefefefe,0x89abcdef,0xefefefef"
# Uncomment to disable graphical terminal (grub-pc only)
#GRUB_TERMINAL=console
# The resolution used on graphical terminal
# note that you can use only modes which your graphic card supports via VBE
# you can see them in real GRUB with the command `vbeinfo'
#GRUB_GFXMODE=640x480
# Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux
#GRUB_DISABLE_LINUX_UUID=true
# Uncomment to disable generation of recovery mode menu entries
#GRUB_DISABLE_RECOVERY="true"
# Uncomment to get a beep at grub start
#GRUB_INIT_TUNE="480 440 1"

View File

@ -0,0 +1,16 @@
# The loopback network interface
auto lo
iface lo inet loopback
# The primary network interface
auto xenbr0
iface xenbr0 inet dhcp
gateway 10.0.2.2
bridge_ports eth0
auto eth0
iface eth0 inet dhcp
pre-up iptables-save < /etc/iptables.save
pre-up /etc/init.d/ebtables load

View File

@ -0,0 +1 @@
bridge

View File

@ -0,0 +1 @@
TOOLSTACK=xapi

View File

@ -0,0 +1,171 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: xend
# Required-Start: $remote_fs
# Required-Stop: $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: XEN control daemon
# Description: XEN control daemon
### END INIT INFO
PATH=/usr/lib/xen-common/bin:/sbin:/bin:/usr/sbin:/usr/bin
DESC="Xen daemons"
VERSION=$(xen-version)
ROOT=/usr/lib/xen-$VERSION
XEND="$ROOT"/bin/xend
XENCONSOLED="$ROOT"/bin/xenconsoled
XENCONSOLED_PIDFILE="/var/run/xenconsoled.pid"
XENSTORED="$ROOT"/bin/xenstored
XENSTORED_DIR="/var/run/xenstored"
XENSTORED_PIDFILE="/var/run/xenstore.pid"
[ "$VERSION" ] || exit 0
[ -x "$XEND" ] || exit 0
[ -r /etc/default/xend ] && . /etc/default/xend
. /lib/init/vars.sh
. /lib/lsb/init-functions
modules_setup()
{
modprobe xenfs 2>/dev/null
modprobe xen-evtchn 2>/dev/null
modprobe xen_blkback 2>/dev/null
modprobe xen_netback 2>/dev/null
modprobe xen_gntdev 2>/dev/null
}
xenfs_setup()
{
[ -e "/proc/xen/capabilities" ] && return 0
log_progress_msg "xenfs"
[ -d "/proc/xen" ] || return 1
mount -t xenfs xenfs /proc/xen || return 1
return 0
}
capability_check()
{
[ -e "/proc/xen/capabilities" ] || return 1
grep -q "control_d" /proc/xen/capabilities || return 1
return 0
}
xend_start()
{
log_progress_msg "xend"
$XEND status && return 1
$XEND start || return 2
i=0
while [ $i -lt 10 ]; do
$XEND status && return 0 || true
i=$(($i + 1))
sleep 1
done
return 2
}
xend_stop()
{
log_progress_msg "xend"
$XEND status || return 0
$XEND stop || return 1
}
xenconsoled_start()
{
log_progress_msg "xenconsoled"
start-stop-daemon --start --quiet --pidfile "$XENCONSOLED_PIDFILE" --exec "$XENCONSOLED" --test > /dev/null \
|| return 1
start-stop-daemon --start --quiet --pidfile "$XENCONSOLED_PIDFILE" --exec "$XENCONSOLED" -- \
$XENCONSOLED_ARGS --pid-file="$XENCONSOLED_PIDFILE" \
|| return 2
}
xenstored_start()
{
log_progress_msg "xenstored"
start-stop-daemon --start --quiet --pidfile "$XENSTORED_PIDFILE" --exec "$XENSTORED" --test > /dev/null \
|| return 1
[ -d "$XENSTORED_DIR" ] || mkdir -p "$XENSTORED_DIR"
export XENSTORED_ROOTDIR="$XENSTORED_DIR"
start-stop-daemon --start --quiet --pidfile "$XENSTORED_PIDFILE" --exec "$XENSTORED" -- \
$XENSTORED_ARGS --pid-file="$XENSTORED_PIDFILE" \
|| return 2
}
case "$1" in
start)
log_daemon_msg "Starting $DESC"
modules_setup
xenfs_setup
case "$?" in
0) ;;
*) log_end_msg 1; exit ;;
esac
capability_check
case "$?" in
0) ;;
*) log_end_msg 255; exit ;;
esac
xenstored_start
case "$?" in
0|1) ;;
*) log_end_msg 1; exit ;;
esac
xenconsoled_start
case "$?" in
0|1) ;;
*) log_end_msg 1; exit ;;
esac
#xend_start
case "$?" in
0|1) ;;
*) log_end_msg 1; exit ;;
esac
log_end_msg 0
;;
stop)
capability_check
case "$?" in
0) ;;
*) exit ;;
esac
log_daemon_msg "Stopping $DESC"
#xend_stop
case "$?" in
0|1) log_end_msg 0 ;;
*) log_end_msg 1 ;;
esac
;;
restart|force-reload)
capability_check
case "$?" in
0) ;;
*) exit ;;
esac
log_daemon_msg "Restarting $DESC"
#xend_stop
case "$?" in
0|1)
#xend_start
case "$?" in
0) log_end_msg 0 ;;
*) log_end_msg 1 ;;
esac
;;
*) log_end_msg 1 ;;
esac
;;
*)
echo "Usage: $0 {start|stop|restart|force-reload}" >&2
exit 3
;;
esac
exit 0

View File

@ -0,0 +1 @@
include puppet-devcloudinitial

View File

@ -0,0 +1,101 @@
class puppet-devcloudinitial {
package { 'linux-headers-3.2.0-23-generic':
ensure => latest,
}
package { 'xen-hypervisor-4.1-amd64':
ensure => latest,
}
package { 'xcp-xapi':
require => Package['xen-hypervisor-4.1-amd64'],
ensure => latest,
}
file { '/etc/xcp/network.conf':
require => Package['xcp-xapi'],
ensure => 'file',
source => 'puppet:///modules/puppet-devcloudinitial/network.conf',
group => '0',
mode => '644',
owner => '0',
}
file { '/etc/init.d/xend':
require => Package['xcp-xapi'],
ensure => 'file',
source => 'puppet:///modules/puppet-devcloudinitial/xend',
group => '0',
owner => '0',
mode => '755',
}
service { 'xendomains':
require => Package['xcp-xapi'],
ensure => 'stopped',
enable => 'false',
}
file { '/etc/default/grub':
require => Package['xen-hypervisor-4.1-amd64'],
ensure => 'file',
source => 'puppet:///modules/puppet-devcloudinitial/grub',
group => '0',
mode => '644',
owner => '0',
}
exec { "/usr/sbin/update-grub":
subscribe => File['/etc/default/grub'],
refreshonly => true,
cwd => '/',
}
file { '/usr/share/qemu':
require => Package['xen-hypervisor-4.1-amd64'],
ensure => 'directory',
group => '0',
mode => '755',
owner => '0',
}
file { '/usr/share/qemu/keymaps':
require => File['/usr/share/qemu'],
ensure => 'link',
group => '0',
mode => '777',
owner => '0',
target => '/usr/share/qemu-linaro/keymaps',
}
file { '/etc/network/interfaces':
ensure => 'file',
source => 'puppet:///modules/puppet-devcloudinitial/interfaces',
group => '0',
mode => '644',
owner => '0',
}
file { '/etc/default/xen':
require => Package['xen-hypervisor-4.1-amd64'],
ensure => 'file',
source => 'puppet:///modules/puppet-devcloudinitial/xen-defaults',
group => '0',
mode => '644',
owner => '0',
}
user { 'root':
ensure => 'present',
comment => 'root',
gid => '0',
home => '/root',
password => '$6$SCixzUjT$sVs9PwR2g7XdHSLnQW5Zsy2dVpVV3qESFV4Joniusbu3BqWUtKgc91vwEDwPhLqyCYM3kKR1.7G9g2Hu/pTQN/',
password_max_age => '99999',
password_min_age => '0',
shell => '/bin/bash',
uid => '0',
}
}

View File

@ -0,0 +1 @@
Nothing in this directory yet, but it will contain the scripts and preconfiguration files to build the basic Ubuntu 12.04 server used in devcloud.

72
tools/devcloud/vagrant/Vagrantfile vendored Normal file
View File

@ -0,0 +1,72 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
Vagrant::Config.run do |config|
config.vm.box = "devcloudbase-ubuntu-12-04-64bit"
# TODO: Get a URL to host the base image
# config.vm.box_url = "http://domain.com/path/to/above.box"
# Uncomment this line to enable the console for debugging the
# build process.
#config.vm.boot_mode = :gui
# Setup port forwarding
config.vm.forward_port 22, 2222
config.vm.forward_port 8080, 8080
config.vm.forward_port 8443, 8443
config.vm.forward_port 5901, 5901
config.vm.forward_port 8787, 8787
config.vm.forward_port 8250, 8250
# Ensure the VM has the right virtual resources
#config.vm.
config.vm.provision :puppet do |puppet|
puppet.manifests_path = "puppet-devcloudinitial"
puppet.manifest_file = "init.pp"
puppet.with_ssh = true
puppet.pp_path = "/etc/puppet"
puppet.module_path = "puppet-devcloudinitial"
end
# Enable provisioning with Puppet stand alone. Puppet manifests
# are contained in a directory path relative to this Vagrantfile.
# You will need to create the manifests directory and a manifest in
# the file my_box.pp in the manifests_path directory.
#
# An example Puppet manifest to provision the message of the day:
#
# # group { "puppet":
# # ensure => "present",
# # }
# #
# # File { owner => 0, group => 0, mode => 0644 }
# #
# # file { '/etc/motd':
# # content => "Welcome to your Vagrant-built virtual machine!
# # Managed by Puppet.\n"
# # }
#
# config.vm.provision :puppet do |puppet|
# puppet.manifests_path = "manifests"
# puppet.manifest_file = "my_box.pp"
# end
end

View File

@ -0,0 +1,43 @@
group { 'vagranttest':
ensure => 'present',
gid => '5000',
}
group { 'admin':
ensure => 'present',
gid => '1002',
}
user { 'vagranttest':
ensure => 'present',
comment => 'vagrant,,,',
gid => '5000',
groups => ['adm', 'cdrom', 'dip', 'plugdev', 'lpadmin', 'sambashare', 'admin'],
home => '/home/vagranttest',
shell => '/bin/bash',
uid => '5000',
}
file { '/home/vagranttest':
ensure => 'directory',
group => '1002',
mode => '755',
owner => '5000',
}
file { '/home/vagranttest/.ssh':
ensure => 'directory',
group => '1002',
mode => '775',
owner => '5000',
}
$auth_key = "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key"
file { '/home/vagranttest/.ssh/authorized_keys':
ensure => 'file',
content => $auth_key,
group => '1002',
mode => '664',
owner => '5000',
}

View File

@ -280,6 +280,8 @@ body.login {
.login .fields .field label.error { .login .fields .field label.error {
color: #FF0000; color: #FF0000;
float: right; float: right;
left: 204px;
top: 0;
} }
.login .fields input { .login .fields input {
@ -10004,3 +10006,7 @@ div.panel.ui-dialog div.list-view div.fixed-header {
background-position: -230px -615px; background-position: -230px -615px;
} }
.label-hovered {
cursor: pointer;
color: blue !important;
}

View File

@ -274,7 +274,7 @@
</div> </div>
<div class="secondary-input hide-if-unselected"> <div class="secondary-input hide-if-unselected">
<input type="radio" name="defaultNetwork" value="new-network" /> <input type="radio" name="defaultNetwork" value="new-network" wizard-field="default-network" />
<div class="name"><fmt:message key="label.default"/></div> <div class="name"><fmt:message key="label.default"/></div>
</div> </div>
</div> </div>
@ -348,7 +348,7 @@
<span wizard-field="hypervisor"></span> <span wizard-field="hypervisor"></span>
</div> </div>
<div class="edit"> <div class="edit">
<a href="1"><fmt:message key="label.edit"/></a> <a href="2"><fmt:message key="label.edit"/></a>
</div> </div>
</div> </div>
@ -397,7 +397,20 @@
<span><fmt:message key="label.network"/></span> <span><fmt:message key="label.network"/></span>
</div> </div>
<div class="value"> <div class="value">
<span wizard-field="default-network"></span> <span wizard-field="default-network" conditional-field="select-network"></span>
</div>
<div class="edit">
<a href="5"><fmt:message key="label.edit"/></a>
</div>
</div>
<!-- Security groups -->
<div class="select odd">
<div class="name">
<span><fmt:message key="label.security.groups"/></span>
</div>
<div class="value">
<span wizard-field="security-groups" conditional-field="select-security-group"></span>
</div> </div>
<div class="edit"> <div class="edit">
<a href="5"><fmt:message key="label.edit"/></a> <a href="5"><fmt:message key="label.edit"/></a>
@ -2034,6 +2047,7 @@ dictionary = {
'label.SR.name ': '<fmt:message key="label.SR.name " />', 'label.SR.name ': '<fmt:message key="label.SR.name " />',
'label.SharedMountPoint': '<fmt:message key="label.SharedMountPoint" />', 'label.SharedMountPoint': '<fmt:message key="label.SharedMountPoint" />',
'label.clvm': '<fmt:message key="label.clvm" />', 'label.clvm': '<fmt:message key="label.clvm" />',
'label.rbd': '<fmt:message key="label.rbd" />',
'label.volgroup': '<fmt:message key="label.volgroup" />', 'label.volgroup': '<fmt:message key="label.volgroup" />',
'label.VMFS.datastore': '<fmt:message key="label.VMFS.datastore" />', 'label.VMFS.datastore': '<fmt:message key="label.VMFS.datastore" />',
'label.network.device': '<fmt:message key="label.network.device" />', 'label.network.device': '<fmt:message key="label.network.device" />',

View File

@ -15,6 +15,7 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
(function(cloudStack) { (function(cloudStack) {
var getProjectAdmin, selectedProjectObj;
cloudStack.projects = { cloudStack.projects = {
requireInvitation: function(args) { requireInvitation: function(args) {
return g_capabilities.projectinviterequired; return g_capabilities.projectinviterequired;
@ -447,12 +448,28 @@
return ['destroy']; return ['destroy'];
} }
if (args.context.multiRule[0].role != 'Admin') { if (args.context.multiRule[0].role != 'Admin' &&
(cloudStack.context.users[0].account == getProjectAdmin || isAdmin() || isDomainAdmin())) { // This is for the new project wizard: check if current logged in User is the Project Owner
return args.context.actions; return args.context.actions;
} }
return []; return [];
}, },
readOnlyCheck: function(args) { // check if current logged in User is the Project Owner
if (isAdmin() || isDomainAdmin())
return true;
var projectOwner, currentUser = cloudStack.context.users[0].account;
$(args.data).each(function() {
var data = this;
if (data.role == 'Admin')
projectOwner = data.username;
});
if (projectOwner == currentUser)
return true;
return false;
},
actions: { actions: {
destroy: { destroy: {
label: 'label.remove.project.account', label: 'label.remove.project.account',
@ -497,7 +514,15 @@
success: function(data) { success: function(data) {
args.response.success({ args.response.success({
_custom: { _custom: {
jobId: data.updateprojectresponse.jobid jobId: data.updateprojectresponse.jobid,
onComplete: function(){
setTimeout(function() {
$(window).trigger('cloudStack.fullRefresh');
if (isUser()) {
$(window).trigger('cloudStack.detailsRefresh');
}
}, 500);
}
}, },
notification: { notification: {
label: 'label.make.project.owner', label: 'label.make.project.owner',
@ -522,6 +547,8 @@
success: function(data) { success: function(data) {
args.response.success({ args.response.success({
data: $.map(data.listprojectaccountsresponse.projectaccount, function(elem) { data: $.map(data.listprojectaccountsresponse.projectaccount, function(elem) {
if (elem.role == 'Owner' || elem.role == 'Admin')
getProjectAdmin = elem.account;
return { return {
id: elem.accountid, id: elem.accountid,
role: elem.role, role: elem.role,
@ -635,6 +662,30 @@
}, },
detailView: { detailView: {
updateContext: function (args) {
var project;
var projectID = args.context.projects[0].id;
var url = 'listProjects';
if (isDomainAdmin()) {
url += '&domainid=' + args.context.users[0].domainid;
}
$.ajax({
url: createURL(url),
data: {
listAll: true,
id: projectID
},
async: false,
success: function(json) {
project = json.listprojectsresponse.project[0]; // override project after update owner
}
});
selectedProjectObj = project;
return {
projects: [project]
};
},
actions: { actions: {
edit: { edit: {
label: 'label.edit', label: 'label.edit',
@ -758,7 +809,7 @@
}, },
tabFilter: function(args) { tabFilter: function(args) {
var project = args.context.projects[0]; var project = selectedProjectObj;
var projectOwner = project.account; var projectOwner = project.account;
var currentAccount = args.context.users[0].account; var currentAccount = args.context.users[0].account;
var hiddenTabs = []; var hiddenTabs = [];

View File

@ -475,6 +475,31 @@ function SharedMountPointURL(server, path) {
return url; return url;
} }
function rbdURL(monitor, pool, id, secret) {
var url;
/*
Replace the + and / symbols by - and _ to have URL-safe base64 going to the API
It's hacky, but otherwise we'll confuse java.net.URI which splits the incoming URI
*/
secret = secret.replace("+", "-");
secret = secret.replace("/", "_");
if (id != null && secret != null) {
monitor = id + ":" + secret + "@" + monitor;
}
if(pool.substring(0,1) != "/")
pool = "/" + pool;
if(monitor.indexOf("://")==-1)
url = "rbd://" + monitor + pool;
else
url = monitor + pool;
return url;
}
function clvmURL(vgname) { function clvmURL(vgname) {
var url; var url;
if(vgname.indexOf("://")==-1) if(vgname.indexOf("://")==-1)

View File

@ -3865,14 +3865,14 @@
fields: [ fields: [
{ {
name: { label: 'label.zone', isEditable: true } name: { label: 'label.zone', isEditable: true, validation: { required: true } }
}, },
{ {
id: { label: 'label.id' }, id: { label: 'label.id' },
allocationstate: { label: 'label.allocation.state' }, allocationstate: { label: 'label.allocation.state' },
dns1: { label: 'label.dns.1', isEditable: true }, dns1: { label: 'label.dns.1', isEditable: true, validation: { required: true } },
dns2: { label: 'label.dns.2', isEditable: true }, dns2: { label: 'label.dns.2', isEditable: true },
internaldns1: { label: 'label.internal.dns.1', isEditable: true }, internaldns1: { label: 'label.internal.dns.1', isEditable: true, validation: { required: true } },
internaldns2: { label: 'label.internal.dns.2', isEditable: true }, internaldns2: { label: 'label.internal.dns.2', isEditable: true },
domainname: { label: 'label.domain' }, domainname: { label: 'label.domain' },
networktype: { label: 'label.network.type' }, networktype: { label: 'label.network.type' },
@ -6293,14 +6293,14 @@
title: 'label.details', title: 'label.details',
fields: [ fields: [
{ {
name: { label: 'label.name', isEditable: true } name: { label: 'label.name', isEditable: true, validation: { required: true } }
}, },
{ {
id: { label: 'label.id' }, id: { label: 'label.id' },
netmask: { label: 'label.netmask', isEditable: true }, netmask: { label: 'label.netmask', isEditable: true, validation: { required: true } },
startip: { label: 'label.start.IP', isEditable: true }, startip: { label: 'label.start.IP', isEditable: true, validation: { required: true } },
endip: { label: 'label.end.IP', isEditable: true }, endip: { label: 'label.end.IP', isEditable: true },
gateway: { label: 'label.gateway', isEditable: true }, gateway: { label: 'label.gateway', isEditable: true, validation: { required: true } },
allocationstate: { allocationstate: {
converter: function(str) { converter: function(str) {
// For localization // For localization
@ -7865,6 +7865,7 @@
var items = []; var items = [];
items.push({id: "nfs", description: "nfs"}); items.push({id: "nfs", description: "nfs"});
items.push({id: "SharedMountPoint", description: "SharedMountPoint"}); items.push({id: "SharedMountPoint", description: "SharedMountPoint"});
items.push({id: "rbd", description: "RBD"});
args.response.success({data: items}); args.response.success({data: items});
} }
else if(selectedClusterObj.hypervisortype == "XenServer") { else if(selectedClusterObj.hypervisortype == "XenServer") {
@ -8048,6 +8049,27 @@
$form.find('.form-item[rel=vCenterDataCenter]').hide(); $form.find('.form-item[rel=vCenterDataCenter]').hide();
$form.find('.form-item[rel=vCenterDataStore]').hide(); $form.find('.form-item[rel=vCenterDataStore]').hide();
} }
else if(protocol == "rbd") {
$form.find('.form-item[rel=rbdmonitor]').css('display', 'inline-block');
$form.find('.form-item[rel=rbdmonitor]').find(".name").find("label").text("RADOS Monitor:");
$form.find('.form-item[rel=rbdpool]').css('display', 'inline-block');
$form.find('.form-item[rel=rbdpool]').find(".name").find("label").text("RADOS Pool:");
$form.find('.form-item[rel=rbdid]').css('display', 'inline-block');
$form.find('.form-item[rel=rbdid]').find(".name").find("label").text("RADOS User:");
$form.find('.form-item[rel=rbdsecret]').css('display', 'inline-block');
$form.find('.form-item[rel=rbdsecret]').find(".name").find("label").text("RADOS Secret:");
$form.find('.form-item[rel=server]').hide();
$form.find('.form-item[rel=iqn]').hide();
$form.find('.form-item[rel=lun]').hide();
$form.find('.form-item[rel=volumegroup]').hide();
$form.find('.form-item[rel=path]').hide();
$form.find('.form-item[rel=vCenterDataCenter]').hide();
$form.find('.form-item[rel=vCenterDataStore]').hide();
}
else { else {
//$dialogAddPool.find("#add_pool_server_container").show(); //$dialogAddPool.find("#add_pool_server_container").show();
$form.find('.form-item[rel=server]').css('display', 'inline-block'); $form.find('.form-item[rel=server]').css('display', 'inline-block');
@ -8116,6 +8138,28 @@
isHidden: true isHidden: true
}, },
// RBD
rbdmonitor: {
label: 'label.rbd.monitor',
validation: { required: true },
isHidden: true
},
rbdpool: {
label: 'label.rbd.pool',
validation: { required: true },
isHidden: true
},
rbdid: {
label: 'label.rbd.id',
validation: { required: false },
isHidden: true
},
rbdsecret: {
label: 'label.rbd.secret',
validation: { required: false },
isHidden: true
},
//always appear (begin) //always appear (begin)
storageTags: { storageTags: {
label: 'label.storage.tags', label: 'label.storage.tags',
@ -8174,6 +8218,14 @@
vg = "/" + vg; vg = "/" + vg;
url = clvmURL(vg); url = clvmURL(vg);
} }
else if (args.data.protocol == "rbd") {
var rbdmonitor = args.data.rbdmonitor;
var rbdpool = args.data.rbdpool;
var rbdid = args.data.rbdid;
var rbdsecret = args.data.rbdsecret;
url = rbdURL(rbdmonitor, rbdpool, rbdid, rbdsecret);
}
else if (args.data.protocol == "vmfs") { else if (args.data.protocol == "vmfs") {
//var path = trim($thisDialog.find("#add_pool_vmfs_dc").val()); //var path = trim($thisDialog.find("#add_pool_vmfs_dc").val());
var path = args.data.vCenterDataCenter; var path = args.data.vCenterDataCenter;

View File

@ -204,11 +204,42 @@
} }
}, },
osTypeId: { osCategory: {
label: 'label.os.type', label: 'OS Category',
select: function(args) { select: function(args) {
$.ajax({ $.ajax({
url: createURL("listOsTypes"), url: createURL("listOsCategories"),
dataType: "json",
async: true,
success: function(json) {
var osCats = json.listoscategoriesresponse.oscategory;
var items = [];
if (isAdmin())
items.push({id: -1, description: "All OS"});
$(osCats).each(function() {
items.push({id: this.id, description: this.name});
});
args.response.success({data: items});
}
});
}
},
osTypeId: {
label: 'label.os.type',
dependsOn: 'osCategory',
select: function(args) {
if(args.osCategory == null)
return;
var apiCmd;
if(args.osCategory == -1)
apiCmd = "listOsTypes";
else
apiCmd = "listOsTypes&oscategoryid=" + args.osCategory;
$.ajax({
url: createURL(apiCmd),
dataType: "json", dataType: "json",
async: true, async: true,
success: function(json) { success: function(json) {
@ -783,15 +814,46 @@
isBoolean: true, isBoolean: true,
isChecked: true isChecked: true
}, },
osCategory: {
label: 'OS Category',
dependsOn: 'isBootable',
select: function(args) {
$.ajax({
url: createURL("listOsCategories"),
dataType: "json",
async: true,
success: function(json) {
var osCats = json.listoscategoriesresponse.oscategory;
var items = [];
if (isAdmin())
items.push({id: -1, description: "All OS"});
$(osCats).each(function() {
items.push({id: this.id, description: this.name});
});
args.response.success({data: items});
}
});
}
},
osTypeId: { osTypeId: {
label: 'label.os.type', label: 'label.os.type',
dependsOn: 'isBootable', dependsOn: ['isBootable','osCategory'],
isHidden: false, isHidden: false,
validation: { required: true }, validation: { required: true },
select: function(args) { select: function(args) {
if(args.osCategory == null)
return;
var apiCmd;
if(args.osCategory == -1)
apiCmd = "listOsTypes";
else
apiCmd = "listOsTypes&oscategoryid=" + args.osCategory;
$.ajax({ $.ajax({
url: createURL("listOsTypes"), url: createURL(apiCmd),
dataType: "json", dataType: "json",
async: true, async: true,
success: function(json) { success: function(json) {

View File

@ -135,7 +135,8 @@
$('<input>') $('<input>')
.attr({ .attr({
type: options.secondary.type, type: options.secondary.type,
name: options.secondary.name name: options.secondary.name,
'wizard-field': options.secondary['wizard-field']
}) })
.val(id) .val(id)
.click(function() { .click(function() {
@ -516,7 +517,8 @@
secondary: { secondary: {
desc: 'Default', desc: 'Default',
name: 'defaultNetwork', name: 'defaultNetwork',
type: 'radio' type: 'radio',
'wizard-field': 'default-network'
} }
}) })
); );
@ -528,7 +530,8 @@
desc: 'description', desc: 'description',
id: 'id' id: 'id'
}, { }, {
type: 'checkbox' type: 'checkbox',
'wizard-field': 'security-groups'
}) })
); );
@ -539,9 +542,6 @@
}, },
'review': function($step, formData) { 'review': function($step, formData) {
return {
response: {
success: function(args) {
$step.find('[wizard-field]').each(function() { $step.find('[wizard-field]').each(function() {
var field = $(this).attr('wizard-field'); var field = $(this).attr('wizard-field');
var fieldName; var fieldName;
@ -552,24 +552,45 @@
if ($input.is('option')) { if ($input.is('option')) {
fieldName = $input.html(); fieldName = $input.html();
} else if ($input.is('input[type=radio]')) { } else if ($input.is('input[type=radio]')) {
// Choosen New network as default
if ($input.parents('div.new-network').size()) {
fieldName = $input.closest('div.new-network').find('input[name="new-network-name"]').val();
// Choosen Network from existed
} else if ($input.parents('div.my-networks').size()) {
fieldName = $input.closest('div.select').find('.select-desc .name').html();
} else {
fieldName = $input.parent().find('.select-desc .name').html(); fieldName = $input.parent().find('.select-desc .name').html();
} }
} else if ($input.eq(0).is('input[type=checkbox]')) {
fieldName = '';
$input.each(function(index) {
if (index != 0) fieldName += '<br />';
fieldName += $(this).next('div.select-desc').find('.name').html();
});
}
if (fieldName) { if (fieldName) {
$(this).html(fieldName); $(this).html(fieldName);
} else { } else {
$(this).html('(' + _l('label.none') + ')'); $(this).html('(' + _l('label.none') + ')');
} }
});
var conditionalFieldFrom = $(this).attr('conditional-field');
if (conditionalFieldFrom) {
if ($wizard.find('.'+conditionalFieldFrom).css('display') == 'block') {
$(this).closest('div.select').show();
} else {
$(this).closest('div.select').hide();
} }
} }
}; });
} }
}; };
// Go to specified step in wizard, // Go to specified step in wizard,
// updating nav items and diagram // updating nav items and diagram
var showStep = function(index) { var showStep = function(index, options) {
if (!options) options = {};
var targetIndex = index - 1; var targetIndex = index - 1;
if (index <= 1) targetIndex = 0; if (index <= 1) targetIndex = 0;

View File

@ -38,11 +38,22 @@
$login.appendTo('html body'); $login.appendTo('html body');
$('html body').addClass('login'); $('html body').addClass('login');
// Remove label if field was auto filled
$.each($form.find('label'), function() {
var $label = $(this);
var $input = $form.find('input').filter(function() {
return $(this).attr('name') == $label.attr('for');
});
if ($input.val()) {
$label.hide();
}
});
// Form validation // Form validation
$form.validate(); $form.validate();
// Form label behavior // Form label behavior
$inputs.bind('keydown keyup focus blur', function(event) { $inputs.bind('keydown focus click blur', function(event) {
var $target = $(event.target); var $target = $(event.target);
var $label = $form.find('label').filter(function() { var $label = $form.find('label').filter(function() {
return $(this).attr('for') == $target.attr('name'); return $(this).attr('for') == $target.attr('name');
@ -52,11 +63,16 @@
$label.hide(); $label.hide();
return true; return true;
} else { } else if (event.type == 'blur') {
if (!$target.val()) { if ($target.hasClass('first-input')) {
$target.removeClass('first-input');
}
if (!$(this).val()) {
$label.show(); $label.show();
} else { }
$label.hide(); } else {
if (!$target.hasClass('first-input')) {
$label.hide();
} }
} }
@ -68,11 +84,13 @@
// Labels cause related input to be focused // Labels cause related input to be focused
$login.find('label').click(function() { $login.find('label').click(function() {
var $input = $inputs.filter('[name=' + $(this).attr('for') + ']'); var $input = $inputs.filter('[name=' + $(this).attr('for') + ']');
var $label = $(this);
$input.focus(); $input.focus();
$label.hide();
}); });
$inputs.filter(':first').focus(); $inputs.filter(':first').addClass('first-input').focus();
// Login action // Login action
$login.find('input[type=submit]').click(function() { $login.find('input[type=submit]').click(function() {

View File

@ -171,7 +171,8 @@
var $input = $('<input>').attr({ var $input = $('<input>').attr({
type: 'text', type: 'text',
name: resource.type, name: resource.type,
value: resource.value value: resource.value,
id: resource.type
}).addClass('required'); }).addClass('required');
$field.append($label, $input); $field.append($label, $input);
@ -305,13 +306,15 @@
.append($('<label>').attr('for', 'project-name').html(_l('label.project.name'))) .append($('<label>').attr('for', 'project-name').html(_l('label.project.name')))
.append($('<input>').addClass('required').attr({ .append($('<input>').addClass('required').attr({
type: 'text', type: 'text',
name: 'project-name' name: 'project-name',
id: 'project-name'
})); }));
var $projectDesc = $('<div>').addClass('field desc') var $projectDesc = $('<div>').addClass('field desc')
.append($('<label>').attr('for', 'project-desc').html(_l('label.display.text'))) .append($('<label>').attr('for', 'project-desc').html(_l('label.display.text')))
.append($('<input>').attr({ .append($('<input>').attr({
type: 'text', type: 'text',
name: 'project-display-text' name: 'project-display-text',
id: 'project-desc'
})); }));
var $submit = $('<input>').attr({ type: 'submit' }).val(_l('label.create.project')); var $submit = $('<input>').attr({ type: 'submit' }).val(_l('label.create.project'));
var $cancel = $('<div>').addClass('button cancel').html(_l('label.cancel')); var $cancel = $('<div>').addClass('button cancel').html(_l('label.cancel'));

View File

@ -831,6 +831,11 @@
$form.find('.form-item .name').each(function() { $form.find('.form-item .name').each(function() {
$(this).html($(this).find('label')); $(this).html($(this).find('label'));
}); });
$form.find('label[for]').each(function() {
var forAttr = $(this).attr('for');
$form.find('#' + forAttr).attr('id', id + '_' + forAttr);
$(this).attr('for', id + '_' + forAttr)
});
$form.find('select, input').change(function() { $form.find('select, input').change(function() {
cloudStack.evenOdd($form, '.field:visible', { cloudStack.evenOdd($form, '.field:visible', {

View File

@ -349,9 +349,26 @@
// Events // Events
$(function() { $(function() {
// Check if target should be hovered
function checkHoveredLabel($target) {
var $multiWizard = $('div.ui-dialog div.multi-wizard');
if (($target.is('label[for]') && !$target.parents('body.login')) ||
($multiWizard.size() &&
($target.is('.multi-wizard label') && $target.prev('input[type="radio"],input[type="checkbox"]').size()) ||
($target.is('.multi-wizard .select-desc div.name') && $target.parent('div.select-desc').prev('input[type="radio"],input[type="checkbox"]').size())
))
return true;
return false;
}
// Rollover behavior for user options // Rollover behavior for user options
$(document).bind('mouseover', function(event) { $(document).bind('mouseover', function(event) {
if ($(event.target).closest('#user, #user-options').size()) { var $target = $(event.target);
if (checkHoveredLabel($target)) {
$target.addClass('label-hovered');
}
if ($target.closest('#user, #user-options').size()) {
return false; return false;
} }
else $('#user-options').hide(); else $('#user-options').hide();
@ -359,11 +376,29 @@
return false; return false;
}); });
$(document).bind('mouseout', function(event) {
var $target = $(event.target);
if (checkHoveredLabel($target)) {
$target.removeClass('label-hovered');
}
});
$(document).bind('click', function(event) { $(document).bind('click', function(event) {
var $target = $(event.target); var $target = $(event.target);
var $container = $target.closest('[cloudStack-container]'); var $container = $target.closest('[cloudStack-container]');
var args = $container.data('cloudStack-args'); var args = $container.data('cloudStack-args');
var $browser = $container.find('#browser .container'); var $browser = $container.find('#browser .container');
var $multiWizard = $('div.ui-dialog div.multi-wizard');
// Wizard: trigger click event for input when click it label
if ($multiWizard.size()) {
if ($target.is('.multi-wizard label') && $target.prev('input[type="radio"],input[type="checkbox"]').size()) {
$target.prev('input').trigger('click');
}
if ($target.is('.multi-wizard .select-desc div.name') && $target.parent('div.select-desc').prev('input[type="radio"],input[type="checkbox"]').size()) {
$target.parent('div.select-desc').prev('input').trigger('click');
}
}
if (!$container.size()) return true; if (!$container.size()) return true;

View File

@ -117,52 +117,56 @@
var $value = $('<div>').addClass('value') var $value = $('<div>').addClass('value')
.appendTo($formItem); .appendTo($formItem);
var $input, $dependsOn, selectFn, selectArgs; var $input, $dependsOn, selectFn, selectArgs;
var dependsOn = field.dependsOn; var dependsOn = $.isArray(field.dependsOn) ? field.dependsOn : [field.dependsOn] ; //now an array
// Depends on fields // Depends on fields
if (field.dependsOn) { if (dependsOn.length) {
$formItem.attr('depends-on', dependsOn); $.each(dependsOn, function(key, value){
$dependsOn = $form.find('input, select').filter(function() { var dependsOn = value;
return $(this).attr('name') === dependsOn;
});
if ($dependsOn.is('[type=checkbox]')) { $formItem.attr('depends-on-'+value, dependsOn);
var isReverse = args.form.fields[dependsOn].isReverse; $dependsOn = $form.find('input, select').filter(function() {
return $(this).attr('name') === dependsOn;
// Checkbox
$dependsOn.bind('click', function(event) {
var $target = $(this);
var $dependent = $target.closest('form').find('[depends-on=\'' + dependsOn + '\']');
if (($target.is(':checked') && !isReverse) ||
($target.is(':unchecked') && isReverse)) {
$dependent.css('display', 'inline-block');
$dependent.each(function() {
if ($(this).data('dialog-select-fn')) {
$(this).data('dialog-select-fn')();
}
});
} else if (($target.is(':unchecked') && !isReverse) ||
($target.is(':checked') && isReverse)) {
$dependent.hide();
}
$dependent.find('input[type=checkbox]').click();
if (!isReverse) {
$dependent.find('input[type=checkbox]').attr('checked', false);
} else {
$dependent.find('input[type=checkbox]').attr('checked', true);
}
return true;
}); });
// Show fields by default if it is reverse checkbox if ($dependsOn.is('[type=checkbox]')) {
if (isReverse) { var isReverse = args.form.fields[dependsOn].isReverse;
$dependsOn.click();
} // Checkbox
} $dependsOn.bind('click', function(event) {
var $target = $(this);
var $dependent = $target.closest('form').find('[depends-on-' + value + '=\'' + dependsOn + '\']');
if (($target.is(':checked') && !isReverse) ||
($target.is(':unchecked') && isReverse)) {
$dependent.css('display', 'inline-block');
$dependent.each(function() {
if ($(this).find('select').data('dialog-select-fn')) {
$(this).find('select').data('dialog-select-fn')();
}
});
} else if (($target.is(':unchecked') && !isReverse) ||
($target.is(':checked') && isReverse)) {
$dependent.hide();
}
$dependent.find('input[type=checkbox]').click();
if (!isReverse) {
$dependent.find('input[type=checkbox]').attr('checked', false);
} else {
$dependent.find('input[type=checkbox]').attr('checked', true);
}
return true;
});
// Show fields by default if it is reverse checkbox
if (isReverse) {
$dependsOn.click();
}
};
});
} }
// Determine field type of input // Determine field type of input
@ -207,31 +211,35 @@
// Pass form item to provider for additional manipulation // Pass form item to provider for additional manipulation
$.extend(selectArgs, { $select: $input }); $.extend(selectArgs, { $select: $input });
if (dependsOn) { if (dependsOn.length) {
$dependsOn = $input.closest('form').find('input, select').filter(function() { $.each(dependsOn, function(key, value){
return $(this).attr('name') === dependsOn; var dependsOn = value;
$dependsOn = $input.closest('form').find('input, select').filter(function() {
return $(this).attr('name') === dependsOn;
});
$dependsOn.bind('change', function(event) {
var $target = $(this);
if (!$dependsOn.is('select')) return true;
var dependsOnArgs = {};
$input.find('option').remove();
if (!$target.children().size()) return true;
dependsOnArgs[dependsOn] = $target.val();
selectFn($.extend(selectArgs, dependsOnArgs));
return true;
});
if (!$dependsOn.is('select')) {
selectFn(selectArgs);
}
}); });
$dependsOn.bind('change', function(event) {
var $target = $(this);
if (!$dependsOn.is('select')) return true;
var dependsOnArgs = {};
$input.find('option').remove();
if (!$target.children().size()) return true;
dependsOnArgs[dependsOn] = $target.val();
selectFn($.extend(selectArgs, dependsOnArgs));
return true;
});
if (!$dependsOn.is('select')) {
selectFn(selectArgs);
}
} else { } else {
selectFn(selectArgs); selectFn(selectArgs);
} }
@ -336,8 +344,12 @@
if(field.validation != null) if(field.validation != null)
$input.data('validation-rules', field.validation); $input.data('validation-rules', field.validation);
else else
$input.data('validation-rules', {}); $input.data('validation-rules', {});
var fieldLabel = field.label;
var inputId = $input.attr('id') ? $input.attr('id') : fieldLabel.replace(/\./g,'_');
$input.attr('id', inputId);
$name.find('label').attr('for', inputId);
}); });
var getFormValues = function() { var getFormValues = function() {

View File

@ -271,6 +271,7 @@
var $panel = args.panel; var $panel = args.panel;
var $container = this.element; var $container = this.element;
var $toHide = $panel.siblings(':not(.always-maximized)'); var $toHide = $panel.siblings(':not(.always-maximized)');
var $shadow = $toHide.find('div.shadow');
if (args.panel.hasClass('maximized')) { if (args.panel.hasClass('maximized')) {
_breadcrumb.filter($panel).removeClass('maximized'); _breadcrumb.filter($panel).removeClass('maximized');
@ -279,6 +280,7 @@
_breadcrumb.filter($panel.siblings()).find('span').animate({ opacity: 1 }); _breadcrumb.filter($panel.siblings()).find('span').animate({ opacity: 1 });
$toHide.animate({ left: _panel.position($container, {}) }, $toHide.animate({ left: _panel.position($container, {}) },
{ duration: 500 }); { duration: 500 });
$shadow.show();
} else { } else {
_breadcrumb.filter($panel).addClass('maximized'); _breadcrumb.filter($panel).addClass('maximized');
$panel.removeClass('reduced'); $panel.removeClass('reduced');
@ -286,6 +288,7 @@
_breadcrumb.filter($panel.siblings()).find('span').animate({ opacity: 0.5 }); _breadcrumb.filter($panel.siblings()).find('span').animate({ opacity: 0.5 });
$toHide.animate(_panel.initialState($container), $toHide.animate(_panel.initialState($container),
{ duration: 500 }); { duration: 500 });
$shadow.hide();
} }
}, },

View File

@ -836,7 +836,7 @@
actionFilter: actionFilter, actionFilter: actionFilter,
data: data, data: data,
context: $detailView.data('view-args').context context: $detailView.data('view-args').context
}).prependTo($firstRow.closest('div.detail-group').closest('.details')); });
// 'View all' button // 'View all' button
var showViewAll = detailViewArgs.viewAll ? var showViewAll = detailViewArgs.viewAll ?
@ -846,6 +846,9 @@
context: context context: context
}) : true }) : true
) : true; ) : true;
if ($actions.find('div.action').size() || (detailViewArgs.viewAll && showViewAll)) {
$actions.prependTo($firstRow.closest('div.detail-group').closest('.details'));
}
if (detailViewArgs.viewAll && showViewAll) { if (detailViewArgs.viewAll && showViewAll) {
$('<div>') $('<div>')
.addClass('view-all') .addClass('view-all')
@ -1035,7 +1038,7 @@
); );
}; };
var replaceTabs = function($detailView, $newTabs, tabs, options) { var replaceTabs = function($detailView, tabs, options) {
var $detailViewElems = $detailView.find('ul.ui-tabs-nav, .detail-group'); var $detailViewElems = $detailView.find('ul.ui-tabs-nav, .detail-group');
$detailView.tabs('destroy'); $detailView.tabs('destroy');
$detailViewElems.remove(); $detailViewElems.remove();
@ -1054,25 +1057,32 @@
); );
}; };
$.fn.detailView = function(args) { $.fn.detailView = function(args, options) {
var $detailView = this; var $detailView = this;
if (options == 'refresh') {
var $tabs = replaceTabs($detailView, args.tabs, {
context: args.context,
tabFilter: args.tabFilter
});
} else {
$detailView.addClass('detail-view');
$detailView.data('view-args', args);
$detailView.addClass('detail-view'); if (args.$listViewRow) {
$detailView.data('view-args', args); $detailView.data('list-view-row', args.$listViewRow);
}
if (args.$listViewRow) { // Create toolbar
$detailView.data('list-view-row', args.$listViewRow); var $toolbar = makeToolbar().appendTo($detailView);
// Create tabs
var $tabs = makeTabs($detailView, args.tabs, {
context: args.context,
tabFilter: args.tabFilter
}).appendTo($detailView);
} }
// Create toolbar
var $toolbar = makeToolbar().appendTo($detailView);
// Create tabs
var $tabs = makeTabs($detailView, args.tabs, {
context: args.context,
tabFilter: args.tabFilter
}).appendTo($detailView);
$detailView.tabs(); $detailView.tabs();
return $detailView; return $detailView;
@ -1151,4 +1161,17 @@
return true; return true;
}); });
// Detail view refresh handler
$(window).bind('cloudStack.detailsRefresh', function() {
var $detailView = $('.detail-view');
$detailView.each(function() {
var $detailView = $(this),
args = $detailView.data('view-args');
$detailView.detailView(args, 'refresh');
});
});
}(window.jQuery, window.cloudStack, window._l)); }(window.jQuery, window.cloudStack, window._l));

View File

@ -675,6 +675,7 @@
var context = args.context; var context = args.context;
var ignoreEmptyFields = args.ignoreEmptyFields; var ignoreEmptyFields = args.ignoreEmptyFields;
var actionPreFilter = args.actionPreFilter; var actionPreFilter = args.actionPreFilter;
var readOnlyCheck = args.readOnlyCheck;
var $thead = $('<tr>').appendTo( var $thead = $('<tr>').appendTo(
$('<thead>').appendTo($inputTable) $('<thead>').appendTo($inputTable)
@ -935,6 +936,11 @@
).appendTo($dataBody); ).appendTo($dataBody);
}); });
if (readOnlyCheck && !readOnlyCheck(args)) {
$multi.find('th.add-user, td.add-user').detach();
$multiForm.find('tbody').detach();
}
_medit.refreshItemWidths($multi); _medit.refreshItemWidths($multi);
}, },
error: cloudStack.dialog.error error: cloudStack.dialog.error

View File

@ -10,6 +10,7 @@ import Utils,Node,Options,Logs,Scripting,Environment,Build,Configure
from os import unlink as _unlink, makedirs as _makedirs, getcwd as _getcwd, chdir as _chdir from os import unlink as _unlink, makedirs as _makedirs, getcwd as _getcwd, chdir as _chdir
from os.path import abspath as _abspath, basename as _basename, dirname as _dirname, exists as _exists, isdir as _isdir, split as _split, join as _join, sep, pathsep, pardir, curdir from os.path import abspath as _abspath, basename as _basename, dirname as _dirname, exists as _exists, isdir as _isdir, split as _split, join as _join, sep, pathsep, pardir, curdir
from glob import glob as _glob from glob import glob as _glob
from subprocess import Popen as _Popen,PIPE
try: set([1,2,3]) try: set([1,2,3])
except Exception: from Sets import set except Exception: from Sets import set
import re import re
@ -31,7 +32,49 @@ filelist = bld.path.ant_glob
distdir = Utils.relpath(_join(sourcedir,"dist")) distdir = Utils.relpath(_join(sourcedir,"dist"))
targetdir = Utils.relpath(_join(sourcedir,"target")) targetdir = Utils.relpath(_join(sourcedir,"target"))
def gitinfo(dir=None):
if dir and not _isdir(dir): return ''
try: p = _Popen(['git','remote','show','-n','origin'],stdin=PIPE,stdout=PIPE,stderr=PIPE,cwd=dir)
except OSError,e:
if e.errno == 2: return '' # svn command is not installed
raise
stdout,stderr = p.communicate('')
retcode = p.wait()
# If the guess fails, just return nothing.
if retcode: return
stdout = [ s.strip() for s in stdout.splitlines() ]
try: url = [ s[11:] for s in stdout if s.startswith("Fetch URL") ][0]
except IndexError: url = [ s[5:] for s in stdout if s.startswith("URL") ][0]
assert url
p = _Popen(['git','log','-1'],stdin=PIPE,stdout=PIPE,stderr=PIPE,cwd=dir)
stdout,stderr = p.communicate('')
retcode = p.wait()
if retcode: return
# If the guess fails, just return nothing.
stdout = [ s.strip() for s in stdout.splitlines() ]
commitid = [ s.split()[1] for s in stdout if s.startswith("commit") ][0]
assert commitid
return "Git Revision: %s"%commitid + "\n" + "Git URL: %s"%url + "\n"
def build_utils_docs (): def build_utils_docs ():
stdout = gitinfo()
if stdout:
f = file("sccs-info","w")
f.write(stdout)
f.flush()
f.close()
else:
if _exists("sccs-info"):
# If the file already existed, we preserve it
return
else:
f = file("sccs-info","w")
f.write("No revision control information could be detected when the source distribution was built.")
f.flush()
f.close()
sccsinfo = _join(sourcedir,"sccs-info") sccsinfo = _join(sourcedir,"sccs-info")
if _exists(sccsinfo): bld.install_files("${DOCDIR}","sccs-info") if _exists(sccsinfo): bld.install_files("${DOCDIR}","sccs-info")
@ -88,19 +131,6 @@ def build_jars ():
bld.install_files ('${JAVADIR}', ant_jars) bld.install_files ('${JAVADIR}', ant_jars)
#def build_python_and_daemonize ():
# obj = bld(features = 'py',name='pythonmodules')
# obj.find_sources_in_dirs('python/lib', exts=['.py'])
#
# if bld.env.DISTRO not in ['Windows','Mac']:
# # build / install declarations of the daemonization utility - except for Windows
# bld(
# name='daemonize',
# features='cc cprogram',
# source='daemonize/daemonize.c',
# target='daemonize/cloud-daemonize'
# )
def build_premium (): def build_premium ():
if buildpremium: bld.recurse(["cloudstack-proprietary/"],'build') if buildpremium: bld.recurse(["cloudstack-proprietary/"],'build')
@ -388,7 +418,6 @@ def build_usage_dir ():
# Get started to execute here # Get started to execute here
build_utils_docs () build_utils_docs ()
build_jars () build_jars ()
#build_python_and_daemonize ()
build_premium () build_premium ()
#build_thirdparty_dir() #build_thirdparty_dir()
build_dependences () build_dependences ()