[Ovirt-devel] [PATCH server] Add LVM volume scanning back into taskomatic.
Ian Main
imain at redhat.com
Wed Feb 4 23:39:43 UTC 2009
This patch adds LVM volume scanning back into taskomatic with the help
of some libvirt-qpid changes that set the LVM volume group name as a
property of the physical volume if applicable.
Also included is a small fix to qmf-libvirt-example to properly sort
volumes by storage pool. This script has been very helpful in debugging
qpid issues both for developers and users.
Signed-off-by: Ian Main <imain at redhat.com>
---
src/task-omatic/taskomatic.rb | 150 +++++++++++++++++++++++++++--------------
1 files changed, 98 insertions(+), 52 deletions(-)
diff --git a/src/task-omatic/taskomatic.rb b/src/task-omatic/taskomatic.rb
index 380be92..9382f2b 100755
--- a/src/task-omatic/taskomatic.rb
+++ b/src/task-omatic/taskomatic.rb
@@ -197,7 +197,17 @@ class TaskOmatic
end
pools = @session.objects(:class => 'pool', 'node' => node.object_id)
- # FIXME: We need to undefine LVM volumes first.
+ # We do this in two passes, first undefine/destroys LVM pools, then
+ # we do physical pools.
+ pools.each do |pool|
+ # libvirt-qpid sets parentVolume to the name of the parent volume
+ # if this is an LVM pool, else it leaves it empty.
+ if pool.parentVolume != ''
+ result = pool.destroy
+ result = pool.undefine
+ end
+ end
+
pools.each do |pool|
result = pool.destroy
result = pool.undefine
@@ -482,44 +492,18 @@ class TaskOmatic
raise "Could not find a host within this storage pool to scan the storage server."
end
- def add_volumes_to_db(db_pool, libvirt_pool, owner = nil, group = nil, mode = nil)
- # FIXME: this is currently broken if you do something like:
- # 1. Add an iscsi pool with 3 volumes (lun-1, lun-2, lun-3)
- # 2. Scan it in
- # 3. Remove lun-3 from the pool
- # 4. Re-scan it
- # What will happen is that you will still have lun-3 available in the
- # database, even though it's not available in the pool anymore. It's a
- # little tricky, though; we have to make sure that we don't pull the
- # database entry out from underneath a possibly running VM (or do we?)
- volumes = @session.objects(:class => 'volume',
- 'storagePool' => libvirt_pool.remote_pool.object_id)
- volumes.each do |volume|
- storage_volume = StorageVolume.factory(db_pool.get_type_label)
-
- # NOTE: it is safe (and, in fact, necessary) to use
- # #{storage_volume.volume_name} here without sanitizing it. This is
- # because this is *not* based on user modifiable data, but rather, on an
- # internal implementation detail
- existing_vol = StorageVolume.find(:first, :conditions =>
- ["storage_pool_id = ? AND #{storage_volume.volume_name} = ?",
- db_pool.id, volume.name])
-
- # in this case, this path already exists in the database; just skip
- next if existing_vol
-
- storage_volume = StorageVolume.factory(db_pool.get_type_label)
- storage_volume.path = volume.path
- storage_volume.size = volume.capacity / 1024
- storage_volume.storage_pool_id = db_pool.id
- storage_volume.write_attribute(storage_volume.volume_name, volume.name)
- storage_volume.lv_owner_perms = owner
- storage_volume.lv_group_perms = group
- storage_volume.lv_mode_perms = mode
- storage_volume.state = StorageVolume::STATE_AVAILABLE
- puts "saving storage volume to db."
- storage_volume.save!
- end
+ def add_volume_to_db(db_pool, volume, owner = nil, group = nil, mode = nil)
+ storage_volume = StorageVolume.factory(db_pool.get_type_label)
+ storage_volume.path = volume.path
+ storage_volume.size = volume.capacity / 1024
+ storage_volume.storage_pool_id = db_pool.id
+ storage_volume.write_attribute(storage_volume.volume_name, volume.name)
+ storage_volume.lv_owner_perms = owner
+ storage_volume.lv_group_perms = group
+ storage_volume.lv_mode_perms = mode
+ storage_volume.state = StorageVolume::STATE_AVAILABLE
+ puts "saving storage volume to db."
+ storage_volume.save!
end
# The words "pool" and "volume" are ridiculously overloaded in our context.
@@ -540,24 +524,86 @@ class TaskOmatic
raise "Could not find storage pool" unless db_pool_phys
node = storage_find_suitable_host(db_pool_phys.hardware_pool)
-
- # FIXME: We may want to scan through all the LVM volumes available
- # and just update the database with allocation information.
- # However afaict right now libvirt provides no way for us to know
- # where an LVM pool/volume sits in terms of its physical pool/volume
- # so we're kinda screwed for now for updating the database.
- #
- # Ian
+ # FIXME: this is currently broken if you do something like:
+ # 1. Add an iscsi pool with 3 volumes (lun-1, lun-2, lun-3)
+ # 2. Scan it in
+ # 3. Remove lun-3 from the pool
+ # 4. Re-scan it
+ # What will happen is that you will still have lun-3 available in the
+ # database, even though it's not available in the pool anymore. It's a
+ # little tricky, though; we have to make sure that we don't pull the
+ # database entry out from underneath a possibly running VM (or do we?)
begin
phys_libvirt_pool = LibvirtPool.factory(db_pool_phys)
phys_libvirt_pool.connect(@session, node)
+ db_pool_phys.state = StoragePool::STATE_AVAILABLE
+ db_pool_phys.save!
begin
- # OK, the pool is all set. Add in all of the volumes
- add_volumes_to_db(db_pool_phys, phys_libvirt_pool)
+ # First we do the physical volumes.
+ volumes = @session.objects(:class => 'volume',
+ 'storagePool' => phys_libvirt_pool.remote_pool.object_id)
+ volumes.each do |volume|
+ storage_volume = StorageVolume.factory(db_pool_phys.get_type_label)
+
+ existing_vol = StorageVolume.find(:first, :conditions =>
+ ["storage_pool_id = ? AND #{storage_volume.volume_name} = ?",
+ db_pool_phys.id, volume.name])
+
+ # Only add if it's not already there.
+ if not existing_vol
+ add_volume_to_db(db_pool_phys, volume);
+ else
+ puts "volume #{volume.name} already exists in db.."
+ end
+
+ # Now check for an LVM pool carving up this volume.
+ lvm_name = volume.childLVMName
+ next if lvm_name == ''
+
+ puts "Child LVM exists for this volume - #{lvm_name}"
+ lvm_db_pool = LvmStoragePool.find(:first, :conditions =>
+ [ "vg_name = ?", lvm_name ])
+ if lvm_db_pool == nil
+ lvm_db_pool = LvmStoragePool.new
+ lvm_db_pool[:type] = "LvmStoragePool"
+ # set the LVM pool to the same hardware pool as the underlying storage
+ lvm_db_pool.hardware_pool_id = db_pool_phys.hardware_pool_id
+ lvm_db_pool.vg_name = lvm_name
+ lvm_db_pool.state = StoragePool::STATE_AVAILABLE
+ lvm_db_pool.save!
+ end
- db_pool_phys.state = StoragePool::STATE_AVAILABLE
- db_pool_phys.save!
+ physical_vol = StorageVolume.find(:first, :conditions =>
+ [ "path = ?", volume.path])
+ if physical_vol == nil
+ # Hm. We didn't find the device in the storage volumes already.
+ # something went wrong internally, and we have to bail
+ raise "Storage internal physical volume error"
+ end
+
+ # OK, put the right lvm_pool_id in place
+ physical_vol.lvm_pool_id = lvm_db_pool.id
+ physical_vol.save!
+
+ lvm_libvirt_pool = LibvirtPool.factory(lvm_db_pool)
+ lvm_libvirt_pool.connect(@session, node)
+
+ lvm_volumes = @session.objects(:class => 'volume',
+ 'storagePool' => lvm_libvirt_pool.remote_pool.object_id)
+ lvm_volumes.each do |lvm_volume|
+
+ lvm_storage_volume = StorageVolume.factory(lvm_db_pool.get_type_label)
+ existing_vol = StorageVolume.find(:first, :conditions =>
+ ["storage_pool_id = ? AND #{lvm_storage_volume.volume_name} = ?",
+ lvm_db_pool.id, lvm_volume.name])
+ if not existing_vol
+ add_volume_to_db(lvm_db_pool, lvm_volume, "0744", "0744", "0744");
+ else
+ puts "volume #{lvm_volume.name} already exists in db.."
+ end
+ end
+ end
end
ensure
phys_libvirt_pool.shutdown
--
1.6.0.4
More information about the ovirt-devel
mailing list