Adds CLVM as an option for primary storage. It copies most of the RBD bits, in most cases simply adding an 'else if' or similar. In the managesnapshot.sh we add the ability to manipulate snapshots for the CLVM volumes, as well as a few minor fixes like adjusting the usage for the -b option to reflect that it accepts four arguments (note that it already accepted four args, it just wasn't reflected in the usage).

RB: https://reviews.apache.org/r/6470/
Send-by: shadowsor@gmail.com
This commit is contained in:
Edison Su 2012-08-10 13:32:21 -07:00
parent 7895386a81
commit 263216caa5
9 changed files with 154 additions and 33 deletions

View File

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

View File

@ -2640,13 +2640,19 @@ public class LibvirtComputingResource extends ServerResourceBase implements
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,
DiskDef.diskBus.VIRTIO,
DiskDef.diskFmtType.QCOW2);
} else if (pool.getType() == StoragePoolType.CLVM) {
disk.defBlockBasedDisk(physicalDisk.getPath(), devId,
diskBusType);
} else {
disk.defFileBasedDisk(physicalDisk.getPath(), devId,
diskBusType, DiskDef.diskFmtType.QCOW2);
if (volume.getType() == Volume.Type.DATADISK) {
disk.defFileBasedDisk(physicalDisk.getPath(), devId,
DiskDef.diskBus.VIRTIO,
DiskDef.diskFmtType.QCOW2);
} else {
disk.defFileBasedDisk(physicalDisk.getPath(), devId,
diskBusType, DiskDef.diskFmtType.QCOW2);
}
}
}

View File

@ -78,6 +78,10 @@ public class KVMStoragePoolManager {
if (destPool.getType() == StoragePoolType.RBD) {
return this._storageAdaptor.createDiskFromTemplate(template, name,
KVMPhysicalDisk.PhysicalDiskFormat.RAW, template.getSize(), destPool);
} else if (destPool.getType() == StoragePoolType.CLVM) {
return this._storageAdaptor.createDiskFromTemplate(template, name,
KVMPhysicalDisk.PhysicalDiskFormat.RAW, template.getSize(),
destPool);
} else {
return this._storageAdaptor.createDiskFromTemplate(template, name,
KVMPhysicalDisk.PhysicalDiskFormat.QCOW2,

View File

@ -462,6 +462,8 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
type = StoragePoolType.Filesystem;
} else if (spd.getPoolType() == LibvirtStoragePoolDef.poolType.RBD) {
type = StoragePoolType.RBD;
} else if (spd.getPoolType() == LibvirtStoragePoolDef.poolType.LOGICAL) {
type = StoragePoolType.CLVM;
}
LibvirtStoragePool pool = new LibvirtStoragePool(uuid, storage.getName(),
@ -551,6 +553,8 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
sp = CreateSharedStoragePool(conn, name, host, path);
} else if (type == StoragePoolType.RBD) {
sp = createRBDStoragePool(conn, name, host, port, userInfo, path);
} else if (type == StoragePoolType.CLVM) {
sp = createCLVMStoragePool(conn, name, host, path);
}
}
@ -685,9 +689,15 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
if (destPool.getType() != StoragePoolType.RBD) {
disk = destPool.createPhysicalDisk(newUuid, format, template.getVirtualSize());
Script.runSimpleBashScript("qemu-img create -f "
+ template.getFormat() + " -b " + template.getPath() + " "
+ disk.getPath());
if (format == PhysicalDiskFormat.QCOW2) {
Script.runSimpleBashScript("qemu-img create -f "
+ template.getFormat() + " -b " + template.getPath() + " "
+ disk.getPath());
} else if (format == PhysicalDiskFormat.RAW) {
Script.runSimpleBashScript("qemu-img convert -f "
+ template.getFormat() + " -O raw " + template.getPath()
+ " " + disk.getPath());
}
} else {
disk = new KVMPhysicalDisk(destPool.getSourceDir() + "/" + newUuid, newUuid, destPool);
disk.setFormat(format);

View File

@ -88,7 +88,11 @@ public class LibvirtStoragePool implements KVMStoragePool {
@Override
public PhysicalDiskFormat getDefaultFormat() {
return PhysicalDiskFormat.QCOW2;
if (getStoragePoolType() == StoragePoolType.CLVM) {
return PhysicalDiskFormat.RAW;
} else {
return PhysicalDiskFormat.QCOW2;
}
}
@Override

View File

@ -6,9 +6,9 @@
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@ -16,16 +16,16 @@
# specific language governing permissions and limitations
# under the License.
# $Id: managesnapshot.sh 11601 2010-08-11 17:26:15Z kris $ $HeadURL: svn://svn.lab.vmops.com/repos/branches/2.1.refactor/java/scripts/storage/qcow2/managesnapshot.sh $
# managesnapshot.sh -- manage snapshots for a single disk (create, destroy, rollback)
# managesnapshot.sh -- manage snapshots for a single disk (create, destroy, rollback, backup)
usage() {
printf "Usage: %s: -c <path to disk> -n <snapshot name>\n" $(basename $0) >&2
printf "Usage: %s: -d <path to disk> -n <snapshot name>\n" $(basename $0) >&2
printf "Usage: %s: -r <path to disk> -n <snapshot name>\n" $(basename $0) >&2
printf "Usage: %s: -b <path to disk> -n <snapshot name> -p <dest name>\n" $(basename $0) >&2
printf "Usage: %s: -b <path to disk> -n <snapshot name> -p <dest dir> -t <dest file>\n" $(basename $0) >&2
exit 2
}
@ -40,21 +40,69 @@ then
fi
fi
is_lv() {
# Must be a block device
if [ -b "${1}" ]; then
# But not a volume group or physical volume
lvm vgs "${1}" > /dev/null 2>&1 && return 1
# And a logical volume
lvm lvs "${1}" > /dev/null 2>&1 && return 0
fi
return 1
}
get_vg() {
lvm lvs --noheadings --unbuffered --separator=/ "${1}" | cut -d '/' -f 2
}
get_lv() {
lvm lvs --noheadings --unbuffered --separator=/ "${1}" | cut -d '/' -f 1
}
double_hyphens() {
echo ${1} | sed -e "s/-/--/g"
}
create_snapshot() {
local disk=$1
local snapshotname="$2"
local failed=0
if [ -f "${disk}" ]; then
if [ ${dmsnapshot} = "yes" ] && is_lv ${disk}; then
local lv=`get_lv ${disk}`
local vg=`get_vg ${disk}`
local lv_dm=`double_hyphens ${lv}`
local vg_dm=`double_hyphens ${vg}`
local lvdevice=/dev/mapper/${vg_dm}-${lv_dm}
local lv_bytes=`blockdev --getsize64 ${lvdevice}`
local lv_sectors=`blockdev --getsz ${lvdevice}`
lvm lvcreate --size ${lv_bytes}b --name "${snapshotname}-cow" ${vg} >&2 || return 2
dmsetup suspend ${vg_dm}-${lv_dm} >&2
if dmsetup info -c --noheadings -o name ${vg_dm}-${lv_dm}-real > /dev/null 2>&1; then
echo "0 ${lv_sectors} snapshot ${lvdevice}-real /dev/mapper/${vg_dm}-${snapshotname}--cow p 64" | \
dmsetup create "${vg_dm}-${snapshotname}" >&2 || ( destroy_snapshot ${disk} "${snapshotname}"; return 2 )
dmsetup resume "${vg_dm}-${snapshotname}" >&2 || ( destroy_snapshot ${disk} "${snapshotname}"; return 2 )
else
dmsetup table ${vg_dm}-${lv_dm} | dmsetup create ${vg_dm}-${lv_dm}-real >&2 || ( destroy_snapshot ${disk} "${snapshotname}"; return 2 )
dmsetup resume ${vg_dm}-${lv_dm}-real >&2 || ( destroy_snapshot ${disk} "${snapshotname}"; return 2 )
echo "0 ${lv_sectors} snapshot ${lvdevice}-real /dev/mapper/${vg_dm}-${snapshotname}--cow p 64" | \
dmsetup create "${vg_dm}-${snapshotname}" >&2 || ( destroy_snapshot ${disk} "${snapshotname}"; return 2 )
echo "0 ${lv_sectors} snapshot-origin ${lvdevice}-real" | \
dmsetup load ${vg_dm}-${lv_dm} >&2 || ( destroy_snapshot ${disk} "${snapshotname}"; return 2 )
dmsetup resume "${vg_dm}-${snapshotname}" >&2 || ( destroy_snapshot ${disk} "${snapshotname}"; return 2 )
fi
dmsetup resume "${vg_dm}-${lv_dm}" >&2
elif [ -f "${disk}" ]; then
$qemu_img snapshot -c "$snapshotname" $disk
if [ $? -gt 0 ]
then
failed=2
printf "***Failed to create snapshot $snapshotname for path $disk\n" >&2
$qemu_img snapshot -d "$snapshotname" $disk
if [ $? -gt 0 ]
then
printf "***Failed to delete snapshot $snapshotname for path $disk\n" >&2
@ -65,26 +113,46 @@ create_snapshot() {
printf "***Failed to create snapshot $snapshotname, undefined type $disk\n" >&2
fi
return $failed
return $failed
}
destroy_snapshot() {
local disk=$1
local snapshotname=$2
local snapshotname="$2"
local failed=0
if [ -f $disk ]; then
if is_lv ${disk}; then
local lv=`get_lv ${disk}`
local vg=`get_vg ${disk}`
local lv_dm=`double_hyphens ${lv}`
local vg_dm=`double_hyphens ${vg}`
if [ -e /dev/mapper/${vg_dm}-${lv_dm}-real ]; then
local dm_refcount=`dmsetup info -c --noheadings -o open ${vg_dm}-${lv_dm}-real`
if [ ${dm_refcount} -le 2 ]; then
dmsetup suspend ${vg_dm}-${lv_dm} >&2
dmsetup table ${vg_dm}-${lv_dm}-real | dmsetup load ${vg_dm}-${lv_dm} >&2
dmsetup resume ${vg_dm}-${lv_dm}
dmsetup remove "${vg_dm}-${snapshotname}"
dmsetup remove ${vg_dm}-${lv_dm}-real
else
dmsetup remove "${vg_dm}-${snapshotname}"
fi
else
dmsetup remove "${vg_dm}-${snapshotname}"
fi
lvm lvremove -f "${vg}/${snapshotname}-cow"
elif [ -f $disk ]; then
$qemu_img snapshot -d "$snapshotname" $disk
if [ $? -gt 0 ]
then
failed=2
printf "Failed to delete snapshot $snapshotname for path $disk\n" >&2
fi
fi
else
failed=3
printf "***Failed to delete snapshot $snapshotname, undefined type $disk\n" >&2
fi
return $failed
return $failed
}
rollback_snapshot() {
@ -93,18 +161,19 @@ rollback_snapshot() {
local failed=0
$qemu_img snapshot -a $snapshotname $disk
if [ $? -gt 0 ]
then
printf "***Failed to apply snapshot $snapshotname for path $disk\n" >&2
failed=1
fi
return $failed
return $failed
}
backup_snapshot() {
local disk=$1
local snapshotname=$2
local snapshotname="$2"
local destPath=$3
local destName=$4
@ -113,24 +182,37 @@ backup_snapshot() {
mkdir -p $destPath >& /dev/null
if [ $? -gt 0 ]
then
printf "Failed to create $destPath" >&2
printf "Failed to create $destPath\n" >&2
return 3
fi
fi
if [ -f ${disk} ]; then
# Does the snapshot exist?
if [ ${dmsnapshot} = "yes" ] && is_lv ${disk}; then
local vg=`get_vg ${disk}`
local vg_dm=`double_hyphens ${vg}`
local scriptdir=`dirname ${0}`
if ! dmsetup info -c --noheadings -o name ${vg_dm}-${snapshotname} > /dev/null 2>&1; then
printf "Disk ${disk} has no snapshot called ${snapshotname}.\n" >&2
return 1
fi
${qemu_img} convert -f raw -O qcow2 "/dev/mapper/${vg_dm}-${snapshotname}" "${destPath}/${destName}" || \
( printf "${qemu_img} failed to create backup of snapshot ${snapshotname} for disk ${disk} to ${destPath}.\n" >&2; return 2 )
elif [ -f ${disk} ]; then
# Does the snapshot exist?
$qemu_img snapshot -l $disk|grep -w "$snapshotname" >& /dev/null
if [ $? -gt 0 ]
then
printf "there is no $snapshotname on disk $disk" >&2
printf "there is no $snapshotname on disk $disk\n" >&2
return 1
fi
$qemu_img convert -f qcow2 -O qcow2 -s $snapshotname $disk $destPath/$destName >& /dev/null
if [ $? -gt 0 ]
then
printf "Failed to backup $snapshotname for disk $disk to $destPath" >&2
printf "Failed to backup $snapshotname for disk $disk to $destPath\n" >&2
return 2
fi
else
@ -150,6 +232,8 @@ pathval=
snapshot=
tmplName=
deleteDir=
dmsnapshot=no
dmrollback=no
while getopts 'c:d:r:n:b:p:t:f' OPTION
do
@ -180,6 +264,13 @@ do
esac
done
if modprobe dm-snapshot; then
dmsnapshot=yes
dmsetup targets | grep -q "^snapshot-merge" && dmrollback=yes
fi
[ -z "${snapshot}" ] && usage
[ -b "$pathval" ] && snapshot=`echo "${snapshot}" | md5sum -t | awk '{ print $1 }'`
if [ "$cflag" == "1" ]
@ -192,6 +283,7 @@ then
exit $?
elif [ "$bflag" == "1" ]
then
[ -z "${destPath}" -o -z "${tmplName}" ] && usage
backup_snapshot $pathval $snapshot $destPath $tmplName
exit $?
elif [ "$rflag" == "1" ]

View File

@ -1325,6 +1325,8 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
pool = new StoragePoolVO(StoragePoolType.Filesystem, "localhost", 0, hostPath);
} else if (scheme.equalsIgnoreCase("sharedMountPoint")) {
pool = new StoragePoolVO(StoragePoolType.SharedMountPoint, storageHost, 0, hostPath);
} else if (scheme.equalsIgnoreCase("clvm")) {
pool = new StoragePoolVO(StoragePoolType.CLVM, storageHost, 0, hostPath.replaceFirst("/", ""));
} else if (scheme.equalsIgnoreCase("rbd")) {
if (port == -1) {
port = 6789;
@ -1628,7 +1630,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
s_logger.debug("creating pool " + pool.getName() + " on host " + hostId);
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.PreSetup && pool.getPoolType() != StoragePoolType.OCFS2 && pool.getPoolType() != StoragePoolType.RBD) {
&& pool.getPoolType() != StoragePoolType.PreSetup && pool.getPoolType() != StoragePoolType.OCFS2 && pool.getPoolType() != StoragePoolType.RBD && pool.getPoolType() != StoragePoolType.CLVM) {
s_logger.warn(" Doesn't support storage pool type " + pool.getPoolType());
return false;
}

View File

@ -7510,6 +7510,7 @@
items.push({id: "nfs", description: "nfs"});
items.push({id: "SharedMountPoint", description: "SharedMountPoint"});
items.push({id: "rbd", description: "RBD"});
items.push({id: "clvm", description: "CLVM"});
args.response.success({data: items});
}
else if(selectedClusterObj.hypervisortype == "XenServer") {

View File

@ -966,6 +966,7 @@
var items = [];
items.push({id: "nfs", description: "nfs"});
items.push({id: "SharedMountPoint", description: "SharedMountPoint"});
items.push({id: "clvm", description: "CLVM"});
args.response.success({data: items});
}
else if(selectedClusterObj.hypervisortype == "XenServer") {