Skip to content

Commit 263216c

Browse files
author
Edison Su
committed
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
1 parent 7895386 commit 263216c

9 files changed

Lines changed: 154 additions & 33 deletions

File tree

api/src/com/cloud/storage/Storage.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ public static enum StoragePoolType {
9696
Iscsi(true), // for e.g., ZFS Comstar
9797
ISO(false), // for iso image
9898
LVM(false), // XenServer local LVM SR
99+
CLVM(true),
99100
RBD(true),
100101
SharedMountPoint(true),
101102
VMFS(true), // VMware VMFS storage

plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2640,13 +2640,19 @@ public int compare(VolumeTO arg0, VolumeTO arg1) {
26402640
disk.defNetworkBasedDisk(physicalDisk.getPath().replace("rbd:", ""), pool.getSourceHost(), pool.getSourcePort(),
26412641
pool.getAuthUserName(), pool.getUuid(),
26422642
devId, diskBusType, diskProtocol.RBD);
2643-
} else if (volume.getType() == Volume.Type.DATADISK) {
2644-
disk.defFileBasedDisk(physicalDisk.getPath(), devId,
2645-
DiskDef.diskBus.VIRTIO,
2646-
DiskDef.diskFmtType.QCOW2);
2643+
} else if (pool.getType() == StoragePoolType.CLVM) {
2644+
disk.defBlockBasedDisk(physicalDisk.getPath(), devId,
2645+
diskBusType);
26472646
} else {
2648-
disk.defFileBasedDisk(physicalDisk.getPath(), devId,
2649-
diskBusType, DiskDef.diskFmtType.QCOW2);
2647+
if (volume.getType() == Volume.Type.DATADISK) {
2648+
disk.defFileBasedDisk(physicalDisk.getPath(), devId,
2649+
DiskDef.diskBus.VIRTIO,
2650+
DiskDef.diskFmtType.QCOW2);
2651+
} else {
2652+
disk.defFileBasedDisk(physicalDisk.getPath(), devId,
2653+
diskBusType, DiskDef.diskFmtType.QCOW2);
2654+
}
2655+
26502656
}
26512657

26522658
}

plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ public KVMPhysicalDisk createDiskFromTemplate(KVMPhysicalDisk template, String n
7878
if (destPool.getType() == StoragePoolType.RBD) {
7979
return this._storageAdaptor.createDiskFromTemplate(template, name,
8080
KVMPhysicalDisk.PhysicalDiskFormat.RAW, template.getSize(), destPool);
81+
} else if (destPool.getType() == StoragePoolType.CLVM) {
82+
return this._storageAdaptor.createDiskFromTemplate(template, name,
83+
KVMPhysicalDisk.PhysicalDiskFormat.RAW, template.getSize(),
84+
destPool);
8185
} else {
8286
return this._storageAdaptor.createDiskFromTemplate(template, name,
8387
KVMPhysicalDisk.PhysicalDiskFormat.QCOW2,

plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,8 @@ public KVMStoragePool getStoragePool(String uuid) {
462462
type = StoragePoolType.Filesystem;
463463
} else if (spd.getPoolType() == LibvirtStoragePoolDef.poolType.RBD) {
464464
type = StoragePoolType.RBD;
465+
} else if (spd.getPoolType() == LibvirtStoragePoolDef.poolType.LOGICAL) {
466+
type = StoragePoolType.CLVM;
465467
}
466468

467469
LibvirtStoragePool pool = new LibvirtStoragePool(uuid, storage.getName(),
@@ -551,6 +553,8 @@ public KVMStoragePool createStoragePool(String name, String host, int port,
551553
sp = CreateSharedStoragePool(conn, name, host, path);
552554
} else if (type == StoragePoolType.RBD) {
553555
sp = createRBDStoragePool(conn, name, host, port, userInfo, path);
556+
} else if (type == StoragePoolType.CLVM) {
557+
sp = createCLVMStoragePool(conn, name, host, path);
554558
}
555559
}
556560

@@ -685,9 +689,15 @@ public KVMPhysicalDisk createDiskFromTemplate(KVMPhysicalDisk template,
685689
if (destPool.getType() != StoragePoolType.RBD) {
686690
disk = destPool.createPhysicalDisk(newUuid, format, template.getVirtualSize());
687691

688-
Script.runSimpleBashScript("qemu-img create -f "
689-
+ template.getFormat() + " -b " + template.getPath() + " "
690-
+ disk.getPath());
692+
if (format == PhysicalDiskFormat.QCOW2) {
693+
Script.runSimpleBashScript("qemu-img create -f "
694+
+ template.getFormat() + " -b " + template.getPath() + " "
695+
+ disk.getPath());
696+
} else if (format == PhysicalDiskFormat.RAW) {
697+
Script.runSimpleBashScript("qemu-img convert -f "
698+
+ template.getFormat() + " -O raw " + template.getPath()
699+
+ " " + disk.getPath());
700+
}
691701
} else {
692702
disk = new KVMPhysicalDisk(destPool.getSourceDir() + "/" + newUuid, newUuid, destPool);
693703
disk.setFormat(format);

plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStoragePool.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,11 @@ public String uri() {
8888

8989
@Override
9090
public PhysicalDiskFormat getDefaultFormat() {
91-
return PhysicalDiskFormat.QCOW2;
91+
if (getStoragePoolType() == StoragePoolType.CLVM) {
92+
return PhysicalDiskFormat.RAW;
93+
} else {
94+
return PhysicalDiskFormat.QCOW2;
95+
}
9296
}
9397

9498
@Override

scripts/storage/qcow2/managesnapshot.sh

Lines changed: 114 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,26 @@
66
# to you under the Apache License, Version 2.0 (the
77
# "License"); you may not use this file except in compliance
88
# with the License. You may obtain a copy of the License at
9-
#
9+
#
1010
# http://www.apache.org/licenses/LICENSE-2.0
11-
#
11+
#
1212
# Unless required by applicable law or agreed to in writing,
1313
# software distributed under the License is distributed on an
1414
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1515
# KIND, either express or implied. See the License for the
1616
# specific language governing permissions and limitations
1717
# under the License.
1818

19-
19+
2020

2121
# $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 $
22-
# managesnapshot.sh -- manage snapshots for a single disk (create, destroy, rollback)
22+
# managesnapshot.sh -- manage snapshots for a single disk (create, destroy, rollback, backup)
2323

2424
usage() {
2525
printf "Usage: %s: -c <path to disk> -n <snapshot name>\n" $(basename $0) >&2
2626
printf "Usage: %s: -d <path to disk> -n <snapshot name>\n" $(basename $0) >&2
2727
printf "Usage: %s: -r <path to disk> -n <snapshot name>\n" $(basename $0) >&2
28-
printf "Usage: %s: -b <path to disk> -n <snapshot name> -p <dest name>\n" $(basename $0) >&2
28+
printf "Usage: %s: -b <path to disk> -n <snapshot name> -p <dest dir> -t <dest file>\n" $(basename $0) >&2
2929
exit 2
3030
}
3131

@@ -40,21 +40,69 @@ then
4040
fi
4141
fi
4242

43+
is_lv() {
44+
# Must be a block device
45+
if [ -b "${1}" ]; then
46+
# But not a volume group or physical volume
47+
lvm vgs "${1}" > /dev/null 2>&1 && return 1
48+
# And a logical volume
49+
lvm lvs "${1}" > /dev/null 2>&1 && return 0
50+
fi
51+
return 1
52+
}
53+
54+
get_vg() {
55+
lvm lvs --noheadings --unbuffered --separator=/ "${1}" | cut -d '/' -f 2
56+
}
57+
58+
get_lv() {
59+
lvm lvs --noheadings --unbuffered --separator=/ "${1}" | cut -d '/' -f 1
60+
}
61+
62+
double_hyphens() {
63+
echo ${1} | sed -e "s/-/--/g"
64+
}
65+
4366
create_snapshot() {
4467
local disk=$1
4568
local snapshotname="$2"
4669
local failed=0
4770

48-
if [ -f "${disk}" ]; then
71+
if [ ${dmsnapshot} = "yes" ] && is_lv ${disk}; then
72+
local lv=`get_lv ${disk}`
73+
local vg=`get_vg ${disk}`
74+
local lv_dm=`double_hyphens ${lv}`
75+
local vg_dm=`double_hyphens ${vg}`
76+
local lvdevice=/dev/mapper/${vg_dm}-${lv_dm}
77+
local lv_bytes=`blockdev --getsize64 ${lvdevice}`
78+
local lv_sectors=`blockdev --getsz ${lvdevice}`
79+
80+
lvm lvcreate --size ${lv_bytes}b --name "${snapshotname}-cow" ${vg} >&2 || return 2
81+
dmsetup suspend ${vg_dm}-${lv_dm} >&2
82+
if dmsetup info -c --noheadings -o name ${vg_dm}-${lv_dm}-real > /dev/null 2>&1; then
83+
echo "0 ${lv_sectors} snapshot ${lvdevice}-real /dev/mapper/${vg_dm}-${snapshotname}--cow p 64" | \
84+
dmsetup create "${vg_dm}-${snapshotname}" >&2 || ( destroy_snapshot ${disk} "${snapshotname}"; return 2 )
85+
dmsetup resume "${vg_dm}-${snapshotname}" >&2 || ( destroy_snapshot ${disk} "${snapshotname}"; return 2 )
86+
else
87+
dmsetup table ${vg_dm}-${lv_dm} | dmsetup create ${vg_dm}-${lv_dm}-real >&2 || ( destroy_snapshot ${disk} "${snapshotname}"; return 2 )
88+
dmsetup resume ${vg_dm}-${lv_dm}-real >&2 || ( destroy_snapshot ${disk} "${snapshotname}"; return 2 )
89+
echo "0 ${lv_sectors} snapshot ${lvdevice}-real /dev/mapper/${vg_dm}-${snapshotname}--cow p 64" | \
90+
dmsetup create "${vg_dm}-${snapshotname}" >&2 || ( destroy_snapshot ${disk} "${snapshotname}"; return 2 )
91+
echo "0 ${lv_sectors} snapshot-origin ${lvdevice}-real" | \
92+
dmsetup load ${vg_dm}-${lv_dm} >&2 || ( destroy_snapshot ${disk} "${snapshotname}"; return 2 )
93+
dmsetup resume "${vg_dm}-${snapshotname}" >&2 || ( destroy_snapshot ${disk} "${snapshotname}"; return 2 )
94+
fi
95+
dmsetup resume "${vg_dm}-${lv_dm}" >&2
96+
elif [ -f "${disk}" ]; then
4997
$qemu_img snapshot -c "$snapshotname" $disk
5098

51-
99+
52100
if [ $? -gt 0 ]
53101
then
54102
failed=2
55103
printf "***Failed to create snapshot $snapshotname for path $disk\n" >&2
56104
$qemu_img snapshot -d "$snapshotname" $disk
57-
105+
58106
if [ $? -gt 0 ]
59107
then
60108
printf "***Failed to delete snapshot $snapshotname for path $disk\n" >&2
@@ -65,26 +113,46 @@ create_snapshot() {
65113
printf "***Failed to create snapshot $snapshotname, undefined type $disk\n" >&2
66114
fi
67115

68-
return $failed
116+
return $failed
69117
}
70118

71119
destroy_snapshot() {
72120
local disk=$1
73-
local snapshotname=$2
121+
local snapshotname="$2"
74122
local failed=0
75123

76-
if [ -f $disk ]; then
124+
if is_lv ${disk}; then
125+
local lv=`get_lv ${disk}`
126+
local vg=`get_vg ${disk}`
127+
local lv_dm=`double_hyphens ${lv}`
128+
local vg_dm=`double_hyphens ${vg}`
129+
if [ -e /dev/mapper/${vg_dm}-${lv_dm}-real ]; then
130+
local dm_refcount=`dmsetup info -c --noheadings -o open ${vg_dm}-${lv_dm}-real`
131+
if [ ${dm_refcount} -le 2 ]; then
132+
dmsetup suspend ${vg_dm}-${lv_dm} >&2
133+
dmsetup table ${vg_dm}-${lv_dm}-real | dmsetup load ${vg_dm}-${lv_dm} >&2
134+
dmsetup resume ${vg_dm}-${lv_dm}
135+
dmsetup remove "${vg_dm}-${snapshotname}"
136+
dmsetup remove ${vg_dm}-${lv_dm}-real
137+
else
138+
dmsetup remove "${vg_dm}-${snapshotname}"
139+
fi
140+
else
141+
dmsetup remove "${vg_dm}-${snapshotname}"
142+
fi
143+
lvm lvremove -f "${vg}/${snapshotname}-cow"
144+
elif [ -f $disk ]; then
77145
$qemu_img snapshot -d "$snapshotname" $disk
78146
if [ $? -gt 0 ]
79147
then
80148
failed=2
81149
printf "Failed to delete snapshot $snapshotname for path $disk\n" >&2
82-
fi
150+
fi
83151
else
84152
failed=3
85153
printf "***Failed to delete snapshot $snapshotname, undefined type $disk\n" >&2
86154
fi
87-
return $failed
155+
return $failed
88156
}
89157

90158
rollback_snapshot() {
@@ -93,18 +161,19 @@ rollback_snapshot() {
93161
local failed=0
94162

95163
$qemu_img snapshot -a $snapshotname $disk
96-
164+
97165
if [ $? -gt 0 ]
98166
then
99167
printf "***Failed to apply snapshot $snapshotname for path $disk\n" >&2
100168
failed=1
101169
fi
102-
103-
return $failed
170+
171+
return $failed
104172
}
173+
105174
backup_snapshot() {
106175
local disk=$1
107-
local snapshotname=$2
176+
local snapshotname="$2"
108177
local destPath=$3
109178
local destName=$4
110179

@@ -113,24 +182,37 @@ backup_snapshot() {
113182
mkdir -p $destPath >& /dev/null
114183
if [ $? -gt 0 ]
115184
then
116-
printf "Failed to create $destPath" >&2
185+
printf "Failed to create $destPath\n" >&2
117186
return 3
118187
fi
119188
fi
120189

121-
if [ -f ${disk} ]; then
122-
# Does the snapshot exist?
190+
if [ ${dmsnapshot} = "yes" ] && is_lv ${disk}; then
191+
local vg=`get_vg ${disk}`
192+
local vg_dm=`double_hyphens ${vg}`
193+
local scriptdir=`dirname ${0}`
194+
195+
if ! dmsetup info -c --noheadings -o name ${vg_dm}-${snapshotname} > /dev/null 2>&1; then
196+
printf "Disk ${disk} has no snapshot called ${snapshotname}.\n" >&2
197+
return 1
198+
fi
199+
200+
${qemu_img} convert -f raw -O qcow2 "/dev/mapper/${vg_dm}-${snapshotname}" "${destPath}/${destName}" || \
201+
( printf "${qemu_img} failed to create backup of snapshot ${snapshotname} for disk ${disk} to ${destPath}.\n" >&2; return 2 )
202+
203+
elif [ -f ${disk} ]; then
204+
# Does the snapshot exist?
123205
$qemu_img snapshot -l $disk|grep -w "$snapshotname" >& /dev/null
124206
if [ $? -gt 0 ]
125207
then
126-
printf "there is no $snapshotname on disk $disk" >&2
208+
printf "there is no $snapshotname on disk $disk\n" >&2
127209
return 1
128210
fi
129211

130212
$qemu_img convert -f qcow2 -O qcow2 -s $snapshotname $disk $destPath/$destName >& /dev/null
131213
if [ $? -gt 0 ]
132214
then
133-
printf "Failed to backup $snapshotname for disk $disk to $destPath" >&2
215+
printf "Failed to backup $snapshotname for disk $disk to $destPath\n" >&2
134216
return 2
135217
fi
136218
else
@@ -150,6 +232,8 @@ pathval=
150232
snapshot=
151233
tmplName=
152234
deleteDir=
235+
dmsnapshot=no
236+
dmrollback=no
153237

154238
while getopts 'c:d:r:n:b:p:t:f' OPTION
155239
do
@@ -180,6 +264,13 @@ do
180264
esac
181265
done
182266

267+
if modprobe dm-snapshot; then
268+
dmsnapshot=yes
269+
dmsetup targets | grep -q "^snapshot-merge" && dmrollback=yes
270+
fi
271+
272+
[ -z "${snapshot}" ] && usage
273+
183274
[ -b "$pathval" ] && snapshot=`echo "${snapshot}" | md5sum -t | awk '{ print $1 }'`
184275

185276
if [ "$cflag" == "1" ]
@@ -192,6 +283,7 @@ then
192283
exit $?
193284
elif [ "$bflag" == "1" ]
194285
then
286+
[ -z "${destPath}" -o -z "${tmplName}" ] && usage
195287
backup_snapshot $pathval $snapshot $destPath $tmplName
196288
exit $?
197289
elif [ "$rflag" == "1" ]

server/src/com/cloud/storage/StorageManagerImpl.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,8 @@ public StoragePoolVO createPool(CreateStoragePoolCmd cmd) throws ResourceInUseEx
13251325
pool = new StoragePoolVO(StoragePoolType.Filesystem, "localhost", 0, hostPath);
13261326
} else if (scheme.equalsIgnoreCase("sharedMountPoint")) {
13271327
pool = new StoragePoolVO(StoragePoolType.SharedMountPoint, storageHost, 0, hostPath);
1328+
} else if (scheme.equalsIgnoreCase("clvm")) {
1329+
pool = new StoragePoolVO(StoragePoolType.CLVM, storageHost, 0, hostPath.replaceFirst("/", ""));
13281330
} else if (scheme.equalsIgnoreCase("rbd")) {
13291331
if (port == -1) {
13301332
port = 6789;
@@ -1628,7 +1630,7 @@ public boolean createStoragePool(long hostId, StoragePoolVO pool) {
16281630
s_logger.debug("creating pool " + pool.getName() + " on host " + hostId);
16291631
if (pool.getPoolType() != StoragePoolType.NetworkFilesystem && pool.getPoolType() != StoragePoolType.Filesystem && pool.getPoolType() != StoragePoolType.IscsiLUN
16301632
&& pool.getPoolType() != StoragePoolType.Iscsi && pool.getPoolType() != StoragePoolType.VMFS && pool.getPoolType() != StoragePoolType.SharedMountPoint
1631-
&& pool.getPoolType() != StoragePoolType.PreSetup && pool.getPoolType() != StoragePoolType.OCFS2 && pool.getPoolType() != StoragePoolType.RBD) {
1633+
&& pool.getPoolType() != StoragePoolType.PreSetup && pool.getPoolType() != StoragePoolType.OCFS2 && pool.getPoolType() != StoragePoolType.RBD && pool.getPoolType() != StoragePoolType.CLVM) {
16321634
s_logger.warn(" Doesn't support storage pool type " + pool.getPoolType());
16331635
return false;
16341636
}

ui/scripts/system.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7510,6 +7510,7 @@
75107510
items.push({id: "nfs", description: "nfs"});
75117511
items.push({id: "SharedMountPoint", description: "SharedMountPoint"});
75127512
items.push({id: "rbd", description: "RBD"});
7513+
items.push({id: "clvm", description: "CLVM"});
75137514
args.response.success({data: items});
75147515
}
75157516
else if(selectedClusterObj.hypervisortype == "XenServer") {

ui/scripts/zoneWizard.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,7 @@
966966
var items = [];
967967
items.push({id: "nfs", description: "nfs"});
968968
items.push({id: "SharedMountPoint", description: "SharedMountPoint"});
969+
items.push({id: "clvm", description: "CLVM"});
969970
args.response.success({data: items});
970971
}
971972
else if(selectedClusterObj.hypervisortype == "XenServer") {

0 commit comments

Comments
 (0)