Class: QemuToolkit::VMStorage

Inherits:
Object
  • Object
show all
Defined in:
lib/qemu-toolkit/vm_storage.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, backend) ⇒ VMStorage

Returns a new instance of VMStorage.



3
4
5
6
# File 'lib/qemu-toolkit/vm_storage.rb', line 3

def initialize(name, backend)
  @name = name
  @backend = backend
end

Instance Attribute Details

#backendObject (readonly)

Returns the value of attribute backend.



8
9
10
# File 'lib/qemu-toolkit/vm_storage.rb', line 8

def backend
  @backend
end

#nameObject (readonly)

Returns the value of attribute name.



9
10
11
# File 'lib/qemu-toolkit/vm_storage.rb', line 9

def name
  @name
end

Instance Method Details

#clone(target_name, version) ⇒ Object

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.

Raises:

  • (ArgumentError)


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 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) ⇒ Object



11
12
13
14
15
16
# 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?Boolean

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

Returns:

  • (Boolean)


85
86
87
# File 'lib/qemu-toolkit/vm_storage.rb', line 85

def exist?
  ! export_tag.nil?
end

#exportObject

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



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# 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?Boolean

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.

Returns:

  • (Boolean)


72
73
74
75
76
77
78
79
80
81
# 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

#hideObject

Hides the vm storage from iSCSI.



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# 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

#iqnObject



135
136
137
138
# File 'lib/qemu-toolkit/vm_storage.rb', line 135

def iqn
  _, n = split
  "iqn.2012-01.com.qemu-toolkit:#{n}"
end

#relative_name?Boolean

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

Returns:

  • (Boolean)


131
132
133
# File 'lib/qemu-toolkit/vm_storage.rb', line 131

def relative_name?
  @name.index('/') == nil
end