class QemuToolkit::VMStorage

Attributes

backend[R]
name[R]

Public Class Methods

new(name, backend) click to toggle source
# File lib/qemu-toolkit/vm_storage.rb, line 3
def initialize(name, backend)
  @name = name
  @backend = backend
end

Public Instance Methods

clone(target_name, version) click to toggle source

Clones this vm storage to the given target name. If target_name is given without pool part, clone will live in the same pool as its parent vm storage. The version argument specifies which version should be cloned and must be a recursive snapshot on the parent vm.

# File lib/qemu-toolkit/vm_storage.rb, line 23
def clone(target_name, version)
  raise ArgumentError, "Must specify the dataset path for cloning." \
    if relative_name?
  
  path, vm_name = split
  target_path = join path, target_name
  backend.zfs :clone, "#@name@#{version}", target_path
  
  backend.disks(name).each do |disk_path|
    disk_name = subtract @name, disk_path
    target_disk_name = join path, target_name, disk_name
    backend.zfs :clone, "#{disk_path}@#{version}", target_disk_name
  end
  
  # Mark the dataset as hidden
  backend.zfs :set, "#{QemuToolkit::EXPORT_TAG}=false", join(path, target_name)
end
create(sizes) click to toggle source
# File lib/qemu-toolkit/vm_storage.rb, line 11
def create(sizes)
  backend.zfs :create, "-o #{QemuToolkit::EXPORT_TAG}=false", name
  sizes.each_with_index do |size, idx|
    backend.zfs :create, "-V #{size}", name + "/disk#{idx+1}"
  end
end
exist?() click to toggle source

Returns true if the storage seems to exist and be a valid vm storage.

# File lib/qemu-toolkit/vm_storage.rb, line 85
def exist?
  ! export_tag.nil?
end
export() click to toggle source

Exports all disks of a virtual machine (called ‘diskN’ below the main dataset) as LUNs below a single iqn for the machine.

# File lib/qemu-toolkit/vm_storage.rb, line 44
def export
  fail "VM storage #{name} does not exist." unless exist?
  fail "VM storage #{name} is already exported." if exported?
  
  path, vm_name = split
  
  backend.stmfadm 'create-tg', vm_name
  
  backend.disks(name).each do |disk_path|
    output = backend.stmfadm 'create-lu', "/dev/zvol/rdsk/"+disk_path
    
    md=output.match /Logical unit created: ([0-9A-F]+)/
    raise "Could not parse created LU. (#{output.inspect})" unless md
    
    backend.stmfadm 'add-view', "-t #{vm_name}", md[1]
  end
  
  backend.stmfadm 'add-tg-member', "-g #{vm_name}", iqn
  backend.itadm 'create-target', "-n #{iqn}", '-t frontend'
  
  # Mark the dataset as exported
  backend.zfs :set, "#{QemuToolkit::EXPORT_TAG}=true", name
end
exported?() click to toggle source

Returns true if the storage exists and is exported currently. Returns false if the storage exists and is not exported. In all other cases this method returns nil.

# File lib/qemu-toolkit/vm_storage.rb, line 72
def exported?
  case (export_tag || '').chomp
    when 'true'
      return true
    when 'false'
      return false
  end
  
  return nil
end
hide() click to toggle source

Hides the vm storage from iSCSI.

# File lib/qemu-toolkit/vm_storage.rb, line 91
def hide
  fail "VM storage #{name} does not exist." unless exist?
  fail "VM storage #{name} is already hidden." unless exported?

  path, vm_name = split
  
  raise "Cannot find an exported dataset named #{name}. " \
    unless exported?
  
  backend.stmfadm 'offline-target', iqn
  backend.itadm 'delete-target', iqn
  
  # Parse existing lus, look for vm_name/diskN
  lus = backend.stmfadm 'list-lu', '-v'
  last_lu = nil
  lus.each_line do |line|
    if md=line.match(/LU Name: ([0-9A-F]+)/)
      last_lu = md[1]
    end
    if line.include?('Data File') && 
      line.include?('/dev/zvol/rdsk') && 
      line.match(%r(/#{Regexp.escape(vm_name)}/disk\d+))
      
      backend.stmfadm 'delete-lu', last_lu
    end
  end
  
  backend.stmfadm 'delete-tg', vm_name

  # Mark the dataset as hidden
  backend.zfs :set, "#{QemuToolkit::EXPORT_TAG}=false", name
end
iqn() click to toggle source
# File lib/qemu-toolkit/vm_storage.rb, line 135
def iqn
  _, n = split
  "iqn.2012-01.com.qemu-toolkit:#{n}"
end
relative_name?() click to toggle source

Returns whether the name used to construct this instance is relative or absolute. A relative name identifies a storage within its pool, an absolute name identifies it within the whole system.

VMStorage.new('foo').relative_name?     # => true
VMStorage.new('b1/foo').relative_name?  # => false
# File lib/qemu-toolkit/vm_storage.rb, line 131
def relative_name?
  @name.index('/') == nil
end

Private Instance Methods

export_tag() click to toggle source

Returns the (cached) value of QemuToolkit::EXPORT_TAG of this storage. This does nothing more than execute

zfs get -Ho value #{QemuToolkit::EXPORT_TAG} NAME

and handle an exception by returning nil.

# File lib/qemu-toolkit/vm_storage.rb, line 147
def export_tag
  @export_tag ||= begin
    backend.zfs :get, "-Ho value #{QemuToolkit::EXPORT_TAG}", name
  rescue 
    nil
  end
end
join(*args) click to toggle source

Joins parts of a vm storage name.

# File lib/qemu-toolkit/vm_storage.rb, line 167
def join(*args)
  File.join(*args)
end
split() click to toggle source

Returns a pair of dataset path and dataset name for the vm storage.

@example

VMStorage.new('foo/bar/baz').split 
# => ['foo/bar', 'baz']
# File lib/qemu-toolkit/vm_storage.rb, line 161
def split
  File.split(@name)
end
subtract(prefix, string) click to toggle source

Subtracts a prefix from a given string.

@example

subtract 'foo', 'foo/bar' # => '/bar'
# File lib/qemu-toolkit/vm_storage.rb, line 175
def subtract(prefix, string)
  raise ArgumentError unless string.start_with?(prefix)
  string[prefix.size..-1]
end