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

From Xen
(Created page with "LVM backed XFS SR Ive created a Logical Volume under Kubuntu 11.10 with XFS and Kronos installed The following is what was required: install lvm2 and xfstools "apt-get install …")
 
Line 35: Line 35:
   
 
Enjoy
 
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')
  +
  +
# 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
  +
  +
# 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)
  +
  +
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)
  +
  +
try:
  +
util.pread2(["mkfs.xfs", self.remotepath])
  +
except util.CommandException, inst:
  +
raise xs_errors.XenError('LVMFilesystem', \
  +
opterr='mkfs failed error %d' % inst.code)
  +
  +
#Update serial number string
  +
scsiutil.add_serial_record(self.session, self.sr_ref, \
  +
scsiutil.devlist_to_serialstring(self.root.split(',')))
  +
  +
def vdi(self, uuid, loadLocked = False):
  +
if not loadLocked:
  +
return EXTFileVDI(self, uuid)
  +
return EXTFileVDI(self, uuid)
  +
  +
def _checkmount(self):
  +
return self.path and os.path.ismount(self.path)
  +
  +
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
  +
  +
return super(EXTFileVDI, self).attach(sr_uuid, vdi_uuid)
  +
  +
  +
if __name__ == '__main__':
  +
SRCommand.run(EXTSR, DRIVER_INFO)
  +
else:
  +
SR.registerSR(EXTSR)
  +
------------SNIP-----------------------

Revision as of 02:37, 21 December 2011

LVM backed XFS SR Ive created a Logical Volume under Kubuntu 11.10 with XFS and Kronos installed 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

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

  1. !/usr/bin/env python
  2. Copyright (C) 2006-2007 XenSource Ltd.
  3. Copyright (C) 2008-2009 Citrix Ltd.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published
  6. by the Free Software Foundation; version 2.1 only.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. Modified for XFS by Scott V. Kamp (outbackdingo@gmail.com)
  12. XFSSR: Based on local-file storage repository, mounts xfs partition
  13. 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')
           # 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
               # 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)
           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)
       try:
           util.pread2(["mkfs.xfs", self.remotepath])
       except util.CommandException, inst:
           raise xs_errors.XenError('LVMFilesystem', \
                 opterr='mkfs failed error %d' % inst.code)
       #Update serial number string
       scsiutil.add_serial_record(self.session, self.sr_ref, \
                 scsiutil.devlist_to_serialstring(self.root.split(',')))
   def vdi(self, uuid, loadLocked = False):
       if not loadLocked:
           return EXTFileVDI(self, uuid)
       return EXTFileVDI(self, uuid)
   def _checkmount(self):
       return self.path and os.path.ismount(self.path)

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
       return super(EXTFileVDI, self).attach(sr_uuid, vdi_uuid)


if __name__ == '__main__':

   SRCommand.run(EXTSR, DRIVER_INFO)

else:

   SR.registerSR(EXTSR)

SNIP-----------------------