Difference between revisions of "Creating a LVM backed XFS SR"

From Xen
m (added a link to a place to get XFSSR.py ... thanks for the howto)
 
(3 intermediate revisions by 2 users not shown)
Line 1: Line 1:
LVM backed XFS SR
+
LVM-backed XFS SR
  +
----
Ive created a Logical Volume under Kubuntu 11.10 with XFS and Kronos installed
 
  +
  +
These instructions were fist tested on a Kubuntu 11.10 system, but should work with any Ubuntu/Debian Kronos-based system to create an LVM-backed XFS SR
  +
 
The following is what was required:
 
The following is what was required:
   
install lvm2 and xfstools
+
Install lvm2 and xfstools.
   
"apt-get install lvm2 xfstools"
+
<pre>apt-get install lvm2 xfstools</pre>
   
create a logical volume
+
Create a logical volume
 
 
 
(If you need help in doing this, there are many tutorials for LVM on the net)
 
(If you need help in doing this, there are many tutorials for LVM on the net)
Line 14: Line 17:
 
Then you must copy the XFSSR.py
 
Then you must copy the XFSSR.py
   
  +
(Get XFSSR.py [http://www.gossamer-threads.com/lists/xen/api/228524 here])
"cp XFSSR.py /usr/lib/xcp/sm/"
 
 
create a symlink to XFSSR
 
 
"cd /usr/lib/xcp/sm/"
 
 
"ln -s XFSSR.py XFSSR"
 
 
once the logical volume is created restart xapi
 
 
"service xcp-xapi restart"
 
 
to create the SR, run
 
 
"SR=`xe sr-create type=xfs device-config:device=/dev/mapper/test-builder name-label=xfs`"
 
 
change '/dev/mapper/test-builder' to your lvm device to match your system
 
 
after its done, youll be able to use the XFS LVM filesystem as the default SR
 
 
Enjoy
 
---------------SNIP XFSSR.py------------------
 
#!/usr/bin/env python
 
# Copyright (C) 2006-2007 XenSource Ltd.
 
# Copyright (C) 2008-2009 Citrix Ltd.
 
#
 
# This program is free software; you can redistribute it and/or modify
 
# it under the terms of the GNU Lesser General Public License as published
 
# by the Free Software Foundation; version 2.1 only.
 
#
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
# GNU Lesser General Public License for more details.
 
#
 
# Modified for XFS by Scott V. Kamp (outbackdingo@gmail.com)
 
#
 
# XFSSR: Based on local-file storage repository, mounts xfs partition
 
# EXTSR: Based on local-file storage repository, mounts ext partition
 
 
import SR, SRCommand, FileSR, util, lvutil, scsiutil
 
 
import os
 
import tempfile
 
import errno
 
import xs_errors
 
import vhdutil
 
from lock import Lock
 
import cleanup
 
 
CAPABILITIES = ["SR_PROBE","SR_UPDATE", "SR_SUPPORTS_LOCAL_CACHING", \
 
"VDI_CREATE","VDI_DELETE","VDI_ATTACH","VDI_DETACH", \
 
"VDI_UPDATE","VDI_CLONE","VDI_SNAPSHOT","VDI_RESIZE", \
 
"VDI_RESET_ON_BOOT","ATOMIC_PAUSE"]
 
 
CONFIGURATION = [ [ 'device', 'local device path (required) (e.g. /dev/sda3)' ] ]
 
 
DRIVER_INFO = {
 
'name': 'Local EXT3 VHD',
 
'description': 'SR plugin which represents disks as VHD files stored on a local EXT3 filesystem, created inside an LVM volume',
 
'vendor': 'Citrix Systems Inc',
 
'copyright': '(C) 2008 Citrix Systems Inc',
 
'driver_version': '1.0',
 
'required_api_version': '1.0',
 
'capabilities': CAPABILITIES,
 
'configuration': CONFIGURATION
 
}
 
 
EXT_PREFIX = 'XSLocalEXT-'
 
 
class EXTSR(FileSR.FileSR):
 
"""EXT3 Local file storage repository"""
 
def handles(srtype):
 
return srtype == 'xfs'
 
handles = staticmethod(handles)
 
 
def load(self, sr_uuid):
 
self.ops_exclusive = FileSR.OPS_EXCLUSIVE
 
self.lock = Lock(vhdutil.LOCK_TYPE_SR, self.uuid)
 
self.sr_vditype = SR.DEFAULT_TAP
 
if not self.dconf.has_key('device') or not self.dconf['device']:
 
raise xs_errors.XenError('ConfigDeviceMissing')
 
 
self.root = self.dconf['device']
 
for dev in self.root.split(','):
 
if not self._isvalidpathstring(dev):
 
raise xs_errors.XenError('ConfigDeviceInvalid', \
 
opterr='path is %s' % dev)
 
self.path = os.path.join(SR.MOUNT_BASE, sr_uuid)
 
self.vgname = EXT_PREFIX + sr_uuid
 
self.remotepath = os.path.join("/dev",self.vgname,sr_uuid)
 
self.attached = self._checkmount()
 
 
def delete(self, sr_uuid):
 
self.attach(sr_uuid)
 
super(EXTSR, self).delete(sr_uuid)
 
self.detach(sr_uuid)
 
 
# Check PVs match VG
 
try:
 
for dev in self.root.split(','):
 
cmd = ["pvs", dev]
 
txt = util.pread2(cmd)
 
if txt.find(self.vgname) == -1:
 
raise xs_errors.XenError('VolNotFound', \
 
opterr='volume is %s' % self.vgname)
 
except util.CommandException, inst:
 
raise xs_errors.XenError('PVSfailed', \
 
opterr='error is %d' % inst.code)
 
 
# Remove LV, VG and pv
 
try:
 
cmd = ["lvremove", "-f", self.remotepath]
 
util.pread2(cmd)
 
 
cmd = ["vgremove", self.vgname]
 
util.pread2(cmd)
 
 
for dev in self.root.split(','):
 
cmd = ["pvremove", dev]
 
util.pread2(cmd)
 
except util.CommandException, inst:
 
raise xs_errors.XenError('LVMDelete', \
 
opterr='errno is %d' % inst.code)
 
 
def attach(self, sr_uuid):
 
if not self._checkmount():
 
try:
 
#Activate LV
 
cmd = ['lvchange','-ay',self.remotepath]
 
util.pread2(cmd)
 
 
# make a mountpoint:
 
if not os.path.isdir(self.path):
 
os.makedirs(self.path)
 
except util.CommandException, inst:
 
raise xs_errors.XenError('LVMMount', \
 
opterr='Unable to activate LV. Errno is %d' % inst.code)
 
 
try:
 
util.pread(["fsck", "-a", self.remotepath])
 
except util.CommandException, inst:
 
if inst.code == 1:
 
util.SMlog("FSCK detected and corrected FS errors. Not fatal.")
 
else:
 
raise xs_errors.XenError('LVMMount', \
 
opterr='FSCK failed on %s. Errno is %d' % (self.remotepath,inst.code))
 
 
try:
 
util.pread(["mount", self.remotepath, self.path])
 
 
FileSR.FileSR.attach(self, sr_uuid)
 
 
self.attached = True
 
except util.CommandException, inst:
 
raise xs_errors.XenError('LVMMount', \
 
opterr='Failed to mount FS. Errno is %d' % inst.code)
 
#Update SCSIid string
 
scsiutil.add_serial_record(self.session, self.sr_ref, \
 
scsiutil.devlist_to_serialstring(self.root.split(',')))
 
 
# Set the block scheduler
 
for dev in self.root.split(','): self.block_setscheduler(dev)
 
 
def detach(self, sr_uuid):
 
if not self._checkmount():
 
return
 
cleanup.abort(self.uuid)
 
try:
 
# Change directory to avoid unmount conflicts
 
os.chdir(SR.MOUNT_BASE)
 
 
# unmount the device
 
util.pread(["umount", self.path])
 
 
# remove the mountpoint
 
os.rmdir(self.path)
 
self.path = None
 
 
# deactivate SR
 
try:
 
cmd = ["lvchange", "-an", self.remotepath]
 
util.pread2(cmd)
 
except util.CommandException, inst:
 
raise xs_errors.XenError('LVMUnMount', \
 
opterr='lvm -an failed errno is %d' % inst.code)
 
 
self.attached = False
 
except util.CommandException, inst:
 
raise xs_errors.XenError('LVMUnMount', \
 
opterr='errno is %d' % inst.code)
 
except:
 
raise xs_errors.XenError('LVMUnMount')
 
 
def probe(self):
 
return lvutil.srlist_toxml(lvutil.scan_srlist(EXT_PREFIX, self.root))
 
 
def create(self, sr_uuid, size):
 
if self._checkmount():
 
raise xs_errors.XenError('SRExists')
 
 
# Check none of the devices already in use by other PBDs
 
if util.test_hostPBD_devs(self.session, self.root):
 
raise xs_errors.XenError('SRInUse')
 
 
# Check serial number entry in SR records
 
for dev in self.root.split(','):
 
if util.test_scsiserial(self.session, dev):
 
raise xs_errors.XenError('SRInUse')
 
 
if not lvutil._checkVG(self.vgname):
 
systemroot = util.getrootdev()
 
rootdev = self.root.split(',')[0]
 
# Create PVs for each device
 
for dev in self.root.split(','):
 
if dev in [systemroot, '%s1'%systemroot, '%s2'%systemroot]:
 
raise xs_errors.XenError('Rootdev', \
 
opterr=('Device %s contains core system files, ' \
 
+ 'please use another device') % dev)
 
 
if not os.path.exists(dev):
 
raise xs_errors.XenError('InvalidDev', \
 
opterr=('Device %s does not exist') % dev)
 
 
try:
 
f = os.open("%s" % dev, os.O_RDWR | os.O_EXCL)
 
except:
 
raise xs_errors.XenError('SRInUse')
 
os.close(f)
 
try:
 
# Overwrite the disk header, try direct IO first
 
cmd = ["dd","if=/dev/zero","of=%s" % dev,"bs=1M", \
 
"count=100","oflag=direct"]
 
util.pread2(cmd)
 
except util.CommandException, inst:
 
if inst.code == errno.EPERM:
 
try:
 
cmd = ["dd","if=/dev/zero","of=%s" % dev,"bs=1M", \
 
"count=100"]
 
util.pread2(cmd)
 
except util.CommandException, inst:
 
raise xs_errors.XenError('LVMWrite',
 
opterr='disk %s, error %d' % (dev, inst.code))
 
else:
 
raise xs_errors.XenError('LVMWrite',
 
opterr='disk %s, error %d' % (dev, inst.code))
 
if not lvutil._checkPV(dev):
 
try:
 
cmd = ["pvcreate", "--metadatasize", "10M", dev]
 
util.pread2(cmd)
 
except util.CommandException, inst:
 
raise xs_errors.XenError('LVMPartCreate',
 
opterr='disk %s, error %d' % (dev, inst.code))
 
else:
 
raise xs_errors.XenError('LVMPartInUse',
 
opterr='disk %s' % dev)
 
 
# Create VG on first device
 
try:
 
cmd = ["vgcreate", self.vgname, rootdev]
 
util.pread2(cmd)
 
except :
 
raise xs_errors.XenError('LVMGroupCreate')
 
   
  +
<pre>cp XFSSR.py /usr/lib/xcp/sm/</pre>
# Then add any additional devs into the VG
 
for dev in self.root.split(',')[1:]:
 
try:
 
cmd = ["vgextend", self.vgname, dev]
 
util.pread2(cmd)
 
except util.CommandException, inst:
 
# One of the PV args failed, delete SR
 
try:
 
cmd = ["vgremove", self.vgname]
 
util.pread2(cmd)
 
except:
 
pass
 
raise xs_errors.XenError('LVMGroupCreate')
 
if lvutil._checkLV(self.remotepath):
 
raise xs_errors.XenError('SRExists')
 
try:
 
numdevs = len(self.root.split(','))
 
cmd = ["lvcreate", "-n", sr_uuid]
 
if numdevs > 1:
 
lowest = -1
 
for dev in self.root.split(','):
 
stats = lvutil._getPVstats(dev)
 
if lowest < 0 or stats['freespace'] < lowest:
 
lowest = stats['freespace']
 
size_mb = (lowest / (1024 * 1024)) * numdevs
 
   
  +
Create a symlink to XFSSR
# Add stripe parameter to command
 
cmd += ["-i", str(numdevs), "-I", "2048"]
 
else:
 
stats = lvutil._getVGstats(self.vgname)
 
size_mb = stats['freespace'] / (1024 * 1024)
 
assert(size_mb > 0)
 
cmd += ["-L", str(size_mb), self.vgname]
 
text = util.pread(cmd)
 
   
  +
<pre>cd /usr/lib/xcp/sm/</pre>
cmd = ["lvchange", "-ay", self.remotepath]
 
text = util.pread(cmd)
 
except util.CommandException, inst:
 
raise xs_errors.XenError('LVMCreate', \
 
opterr='lv operation, error %d' % inst.code)
 
except AssertionError:
 
raise xs_errors.XenError('SRNoSpace', \
 
opterr='Insufficient space in VG %s' % self.vgname)
 
   
  +
<pre>ln -s XFSSR.py XFSSR</pre>
try:
 
util.pread2(["mkfs.xfs", self.remotepath])
 
except util.CommandException, inst:
 
raise xs_errors.XenError('LVMFilesystem', \
 
opterr='mkfs failed error %d' % inst.code)
 
   
  +
Once the logical volume is created, restart xapi
#Update serial number string
 
scsiutil.add_serial_record(self.session, self.sr_ref, \
 
scsiutil.devlist_to_serialstring(self.root.split(',')))
 
   
  +
<pre>service xcp-xapi restart</pre>
def vdi(self, uuid, loadLocked = False):
 
if not loadLocked:
 
return EXTFileVDI(self, uuid)
 
return EXTFileVDI(self, uuid)
 
   
  +
To create the SR, run
def _checkmount(self):
 
return self.path and os.path.ismount(self.path)
 
   
  +
<pre>SR=`xe sr-create type=xfs device-config:device=/dev/mapper/test-builder name-label=xfs`</pre>
class EXTFileVDI(FileSR.FileVDI):
 
def attach(self, sr_uuid, vdi_uuid):
 
try:
 
vdi_ref = self.sr.srcmd.params['vdi_ref']
 
self.session.xenapi.VDI.remove_from_xenstore_data(vdi_ref, \
 
"vdi-type")
 
self.session.xenapi.VDI.remove_from_xenstore_data(vdi_ref, \
 
"storage-type")
 
self.session.xenapi.VDI.add_to_xenstore_data(vdi_ref, \
 
"storage-type", "xfs")
 
except:
 
util.logException("EXTSR:attach")
 
pass
 
   
  +
Change '/dev/mapper/test-builder' to your lvm device to match your system
return super(EXTFileVDI, self).attach(sr_uuid, vdi_uuid)
 
   
  +
After that is done, you'll be able to use the XFS LVM filesystem as the default SR
   
  +
Enjoy!
if __name__ == '__main__':
 
SRCommand.run(EXTSR, DRIVER_INFO)
 
else:
 
SR.registerSR(EXTSR)
 
------------SNIP-----------------------
 

Latest revision as of 15:00, 29 June 2012

LVM-backed XFS SR


These instructions were fist tested on a Kubuntu 11.10 system, but should work with any Ubuntu/Debian Kronos-based system to create an LVM-backed XFS SR

The following is what was required:

Install lvm2 and xfstools.

apt-get install lvm2 xfstools

Create a logical volume

(If you need help in doing this, there are many tutorials for LVM on the net) ( see [1] )

Then you must copy the XFSSR.py

(Get XFSSR.py here)

cp XFSSR.py /usr/lib/xcp/sm/

Create a symlink to XFSSR

cd /usr/lib/xcp/sm/
ln -s XFSSR.py XFSSR

Once the logical volume is created, restart xapi

service xcp-xapi restart

To create the SR, run

SR=`xe sr-create type=xfs device-config:device=/dev/mapper/test-builder name-label=xfs`

Change '/dev/mapper/test-builder' to your lvm device to match your system

After that is done, you'll be able to use the XFS LVM filesystem as the default SR

Enjoy!