Skip to content

Commit

Permalink
F #3297: LXD volatile support
Browse files Browse the repository at this point in the history
(cherry picked from commit ab0dbc7)
  • Loading branch information
rsmontero committed Apr 6, 2020
1 parent de74062 commit d79c71a
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 75 deletions.
51 changes: 26 additions & 25 deletions src/vmm_mad/remotes/lib/lxd/container.rb
Original file line number Diff line number Diff line change
Expand Up @@ -312,15 +312,13 @@ def setup_storage(operation)
return unless @one

@one.get_disks.each do |disk|
next if @one.swap?(disk)
return nil unless setup_disk(disk, operation)
end

return true unless @one.has_context?
return true unless @one.context?

csrc = @lxc['devices']['context']['source'].clone

context = @one.get_context_disk
mapper = FSRawMapper.new
mapper = FSRawMapper.new

if operation == 'map'
mk_context_dir = "#{Mapper::COMMANDS[:su_mkdir]} #{@context_path}"
Expand All @@ -333,51 +331,44 @@ def setup_storage(operation)
end
end

mapper.public_send(operation, @one, context, csrc)
mapper.public_send(operation, @one, @one.context_disk, context_source)
end

# Generate the context devices and maps the context the device
def attach_context
@one.context(@lxc['devices'])

csrc = @lxc['devices']['context']['source'].clone

context = @one.get_context_disk
mapper = FSRawMapper.new

return unless mapper.map(@one, context, csrc)
mapper = FSRawMapper.new
return unless mapper.map(@one, @one.context_disk, context_source)

update
true
end

# Removes the context section from the LXD configuration and unmap the
# context device
# Removes the context section from the LXD configuration and
# unmaps the context device
def detach_context
return true unless @one.has_context?
return true unless @one.context?

csrc = @lxc['devices']['context']['source'].clone
context_src = context_source

@lxc['devices'].delete('context')

update

context = @one.get_context_disk
mapper = FSRawMapper.new

mapper.unmap(@one, context, csrc)
mapper = FSRawMapper.new
mapper.unmap(@one, @one.context_disk, context_src)
end

# Attach disk to container (ATTACH = YES) in VM description
def attach_disk
disk_element = hotplug_disk

raise 'Missing hotplug info' unless disk_element
return if @one.swap?(disk_element)

return unless setup_disk(disk_element, 'map')

disk_hash = @one.disk(disk_element, nil, nil)

@lxc['devices'].update(disk_hash)

update
Expand Down Expand Up @@ -548,10 +539,10 @@ def change_state(action, options)
# TODO This maps should be built dynamically or based on a DISK attribute
# so new mappers does not need to modified source code
def new_disk_mapper(disk)
case disk['TYPE']
when 'FILE', 'BLOCK'
ds = @one.disk_source(disk)

ds = @one.disk_source(disk)
case disk['DISK_TYPE']
when 'FILE', 'BLOCK'
cmd = "#{Mapper::COMMANDS[:file]} #{ds}"

rc, out, err = Command.execute(cmd, false)
Expand Down Expand Up @@ -586,4 +577,14 @@ def new_disk_mapper(disk)
end
end

def context_source
return unless @one.context?

disk_source('context')
end

def disk_source(disk_name)
@lxc['devices'][disk_name]['source'].clone
end

end
79 changes: 48 additions & 31 deletions src/vmm_mad/remotes/lib/lxd/mapper/mapper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ class Mapper
:xfs_growfs => 'sudo xfs_growfs',
:rbd => 'sudo rbd-nbd --id',
:xfs_admin => 'sudo xfs_admin',
:tune2fs => 'sudo tune2fs'
:tune2fs => 'sudo tune2fs',
:mkfs => '/sbin/mkfs'
}

#---------------------------------------------------------------------------
Expand All @@ -86,7 +87,7 @@ class Mapper
# Errors should be log using OpenNebula driver functions
def do_map(_one_vm, _disk, _directory)
OpenNebula.log_error("map function not implemented for #{self.class}")
nil
""
end

# Unmaps a previously mapped partition
Expand All @@ -97,7 +98,7 @@ def do_map(_one_vm, _disk, _directory)
# @return nil
def do_unmap(_device, _one_vm, _disk, _directory)
OpenNebula.log_error("unmap function not implemented for #{self.class}")
nil
""
end

#---------------------------------------------------------------------------
Expand All @@ -120,6 +121,10 @@ def map(one_vm, disk, directory)

return false unless device

if one_vm.volatile?(disk)
return false unless mkfs(device, one_vm.lxdrc[:filesystem])
end

partitions = lsblk(device)

return false unless partitions
Expand Down Expand Up @@ -167,40 +172,40 @@ def unmap(one_vm, disk, directory)

real_path = File.realpath(directory) if !is_rootfs && is_shared_ds

sys_parts.each {|d|
sys_parts.each do |d|
if d['mountpoint'] == real_path
partitions = [d]
device = d['path']
break
end

if d['children']
d['children'].each {|c|
d['children'].each do |c|
next unless c['mountpoint'] == real_path

partitions = d['children']
device = d['path']
break
}
end
end

break unless partitions.empty?
}
end

partitions.delete_if {|p| !p['mountpoint'] }

partitions.sort! {|a, b|
partitions.sort! do |a, b|
b['mountpoint'].length <=> a['mountpoint'].length
}
end

if device.empty?
OpenNebula.log_error("Failed to detect block device from #{directory}")
return true
OpenNebula.log_error("Cannot detect block device from #{directory}")
return false
end

return unless umount(partitions)
return false unless umount(partitions)

return unless do_unmap(device, one_vm, disk, real_path)
return false unless do_unmap(device, one_vm, disk, real_path)

true
end
Expand All @@ -214,11 +219,11 @@ def unmap(one_vm, disk, directory)
# Umounts partitions
# @param partitions [Array] with partition device names
def umount(partitions)
partitions.each {|p|
partitions.each do |p|
next unless p['mountpoint']

return nil unless umount_dev(p['path'])
}
end
end

# Mounts partitions
Expand Down Expand Up @@ -287,15 +292,15 @@ def umount_dev(dev)
# for host partitions
# @return [Hash] with partitions
def lsblk(device)
partitions = {}

rc, o, e = Command.execute("#{COMMANDS[:lsblk]} -OJ #{device}", false)

if rc != 0 || o.empty?
OpenNebula.log_error("lsblk: #{e}")
return
return partitions
end

partitions = nil

begin
partitions = JSON.parse(o)['blockdevices']

Expand All @@ -308,21 +313,21 @@ def lsblk(device)
partitions = [partitions]
end

partitions.delete_if {|p|
p['fstype'].casecmp('swap').zero? if p['fstype']
}
partitions.delete_if do |p|
p['fstype'].casecmp('swap').zero? if p['fstype']
end
end
rescue
rescue StandardError
OpenNebula.log_error("lsblk: error parsing lsblk -OJ #{device}")
return
return {}
end

# Fix for lsblk paths for version < 2.33
partitions.each {|p|
partitions.each do |p|
lsblk_path(p)

p['children'].each {|q| lsblk_path(q) } if p['children']
}
end

partitions
end
Expand Down Expand Up @@ -446,13 +451,13 @@ def parse_fstab(partitions, path, fstab)

next if %w[/ swap].include?(mount_point)

partitions.each {|p|
partitions.each do |p|
next if p[key] != value

return false unless mount_dev(p['path'], path + mount_point)

break
}
end
end

true
Expand Down Expand Up @@ -521,13 +526,14 @@ def reset_fs_uuid(fs_type, device)

cmd = "#{COMMANDS[:tune2fs]} -U random #{device}"
else
return
return true
end

rc, o, e = Command.execute(cmd, false)
return if rc.zero?
return true if rc.zero?

OpenNebula.log_error "#{__method__}: error changing UUID: #{o}\n#{e}\n"
false
end

def get_fstype(device)
Expand All @@ -536,12 +542,12 @@ def get_fstype(device)

fstype = ''

o.each_line {|l|
o.each_line do |l|
next unless (m = l.match(/TYPE=(.*)/))

fstype = m[1]
break
}
end

fstype
end
Expand All @@ -552,4 +558,15 @@ def update_partable(dev)
Command.execute(cmd, false)
end

# Formats a block device
def mkfs(device, format)
cmd = "#{COMMANDS[:mkfs]}.#{format} #{device}"
rc, o, e = Command.execute(cmd, false)

return true if rc.zero?

OpenNebula.log_error "Failed to format #{device}\n#{o}\n#{e}"
false
end

end
Loading

0 comments on commit d79c71a

Please sign in to comment.