mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-21 14:50:08 +03:00
F #1684: LXD fixes path checks
This commit is contained in:
parent
df85e16c75
commit
d746dded35
@ -21,6 +21,7 @@ require 'open3'
|
||||
# This module can be used to execute commands. It wraps popen3 and provides
|
||||
# locking capabilites using flock
|
||||
module Command
|
||||
|
||||
LOCK_FILE = '/tmp/onelxd-lock'
|
||||
|
||||
def self.execute(cmd, block)
|
||||
@ -31,7 +32,7 @@ module Command
|
||||
begin
|
||||
fd = lock if block
|
||||
|
||||
Open3.popen3(cmd) { |i, o, e, t|
|
||||
Open3.popen3(cmd) {|i, o, e, t|
|
||||
rc = t.value.exitstatus
|
||||
|
||||
stdout = o.read
|
||||
@ -41,7 +42,6 @@ module Command
|
||||
e.close
|
||||
}
|
||||
rescue
|
||||
|
||||
ensure
|
||||
unlock(fd) if block
|
||||
end
|
||||
@ -67,11 +67,11 @@ module Command
|
||||
lfd = File.open(LOCK_FILE,"w")
|
||||
lfd.flock(File::LOCK_EX)
|
||||
|
||||
return lfd
|
||||
lfd
|
||||
end
|
||||
|
||||
def self.unlock(lfd)
|
||||
lfd.close
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -236,7 +236,7 @@ class Container
|
||||
rc, _o, e = Command.execute(create_context_dir, false)
|
||||
|
||||
if rc != 0
|
||||
OpenNebula.log_error("setup_storage: #{e}")
|
||||
OpenNebula.log_error("#{__method__}: #{e}")
|
||||
return
|
||||
end
|
||||
|
||||
@ -360,8 +360,8 @@ class Container
|
||||
|
||||
rc, _o, e = Command.execute_once(server, true)
|
||||
|
||||
if rc != 0
|
||||
OpenNebula.log_error("do_map: #{e}")
|
||||
unless [nil, 0].include?(rc)
|
||||
OpenNebula.log_error("#{__method__}: #{e}\nFailed to start vnc")
|
||||
return
|
||||
end
|
||||
|
||||
@ -370,7 +370,6 @@ class Container
|
||||
File.open(pipe, 'a') do |f|
|
||||
f.write command
|
||||
end
|
||||
|
||||
ensure
|
||||
Command.unlock(lfd) if lfd
|
||||
end
|
||||
@ -403,28 +402,29 @@ class Container
|
||||
def new_disk_mapper(disk)
|
||||
case disk['TYPE']
|
||||
when 'FILE'
|
||||
|
||||
ds = "#{@one.sysds_path}/#{@one.vm_id}/disk.#{disk['DISK_ID']}"
|
||||
|
||||
rc, out, err = Command.execute("#{Mapper::COMMANDS[:file]} #{ds}", false)
|
||||
|
||||
unless rc.zero?
|
||||
OpenNebula.log_error("do_map: #{err}")
|
||||
OpenNebula.log_error("#{__method__} #{err}")
|
||||
return
|
||||
end
|
||||
|
||||
case out
|
||||
when /.*QEMU QCOW.*/
|
||||
OpenNebula.log "Using qcow2 mapper for #{ds}"
|
||||
return Qcow2Mapper.new
|
||||
Qcow2Mapper.new
|
||||
when /.*filesystem.*/
|
||||
OpenNebula.log "Using raw filesystem mapper for #{ds}"
|
||||
return FSRawMapper.new
|
||||
FSRawMapper.new
|
||||
when /.*boot sector.*/
|
||||
OpenNebula.log "Using raw disk mapper for #{ds}"
|
||||
return DiskRawMapper.new
|
||||
DiskRawMapper.new
|
||||
else
|
||||
OpenNebula.log("Unknown #{out} image format, trying raw filesystem mapper")
|
||||
return FSRawMapper.new
|
||||
FSRawMapper.new
|
||||
end
|
||||
when 'RBD'
|
||||
OpenNebula.log "Using rbd disk mapper for #{ds}"
|
||||
|
@ -185,40 +185,42 @@ class Mapper
|
||||
sys_parts = lsblk('')
|
||||
|
||||
return false unless sys_parts
|
||||
|
||||
|
||||
partitions = []
|
||||
device = ''
|
||||
real_path = directory
|
||||
|
||||
dir_ok = directory.dup.gsub('//', '/')
|
||||
real_path = dir_ok
|
||||
|
||||
ds = one_vm.sysds_path
|
||||
if File.symlink?(ds)
|
||||
real_ds = File.readlink(ds)
|
||||
real_path = real_ds + directory.split(ds)[-1] if directory.include?(ds)
|
||||
real_path = real_ds + dir_ok.split(ds)[-1] if dir_ok.include?(ds)
|
||||
end
|
||||
|
||||
sys_parts.each { |d|
|
||||
|
||||
sys_parts.each {|d|
|
||||
if d['mountpoint'] == real_path
|
||||
partitions = [d]
|
||||
device = d['path']
|
||||
break
|
||||
end
|
||||
|
||||
|
||||
d['children'].each { |c|
|
||||
if c['mountpoint'] == real_path
|
||||
partitions = d['children']
|
||||
device = d['path']
|
||||
break
|
||||
end
|
||||
} if d['children']
|
||||
|
||||
break if !partitions.empty?
|
||||
}
|
||||
|
||||
partitions.delete_if { |p| !p['mountpoint'] }
|
||||
|
||||
partitions.sort! { |a,b|
|
||||
b['mountpoint'].length <=> a['mountpoint'].length
|
||||
}
|
||||
next unless c['mountpoint'] == real_path
|
||||
|
||||
partitions = d['children']
|
||||
device = d['path']
|
||||
break
|
||||
} if d['children']
|
||||
|
||||
break if !partitions.empty?
|
||||
}
|
||||
|
||||
partitions.delete_if {|p| !p['mountpoint'] }
|
||||
|
||||
partitions.sort! {|a, b|
|
||||
b['mountpoint'].length <=> a['mountpoint'].length
|
||||
}
|
||||
|
||||
if device.empty?
|
||||
OpenNebula.log_error("Failed to detect block device from #{directory}")
|
||||
|
@ -21,6 +21,7 @@ $LOAD_PATH.unshift File.dirname(__FILE__)
|
||||
require 'mapper'
|
||||
|
||||
class Qcow2Mapper < Mapper
|
||||
|
||||
# Max number of block devices. This should be set to the parameter used
|
||||
# to load the nbd kernel module (default in kernel is 16)
|
||||
NBDS_MAX = 256
|
||||
@ -38,7 +39,7 @@ class Qcow2Mapper < Mapper
|
||||
rc, _out, err = Command.execute(cmd, true)
|
||||
|
||||
if rc != 0
|
||||
OpenNebula.log_error("do_map: #{err}")
|
||||
OpenNebula.log_error("#{__method__}: #{err}")
|
||||
return
|
||||
end
|
||||
|
||||
@ -54,7 +55,7 @@ class Qcow2Mapper < Mapper
|
||||
|
||||
return true if rc.zero?
|
||||
|
||||
OpenNebula.log_error("do_unmap: #{err}")
|
||||
OpenNebula.log_error("#{__method__}: #{err}")
|
||||
nil
|
||||
end
|
||||
|
||||
@ -76,8 +77,9 @@ class Qcow2Mapper < Mapper
|
||||
return "/dev/nbd#{i}" unless nbds.include?(i)
|
||||
}
|
||||
|
||||
OpenNebula.log_error("nbd_device: Cannot find free nbd device")
|
||||
OpenNebula.log_error("#{__method__}: Cannot find free nbd device")
|
||||
|
||||
''
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -25,7 +25,7 @@ require 'mapper'
|
||||
#-------------------------------------------------------------------------------
|
||||
class FSRawMapper < Mapper
|
||||
|
||||
def do_map(one_vm, disk, directory)
|
||||
def do_map(one_vm, disk, _directory)
|
||||
dsrc = disk_source(one_vm, disk)
|
||||
cmd = "#{COMMANDS[:losetup]} -f --show #{dsrc}"
|
||||
|
||||
@ -33,23 +33,25 @@ class FSRawMapper < Mapper
|
||||
|
||||
return out.chomp unless rc != 0 || out.empty?
|
||||
|
||||
OpenNebula.log_error("do_map: #{err}")
|
||||
OpenNebula.log_error("#{__method__}: #{err}")
|
||||
nil
|
||||
end
|
||||
|
||||
def do_unmap(device, one_vm, disk, directory)
|
||||
def do_unmap(device, _one_vm, _disk, _directory)
|
||||
cmd = "#{COMMANDS[:losetup]} -d #{device}"
|
||||
|
||||
rc, _out, err = Command.execute(cmd, true)
|
||||
|
||||
return true if rc.zero?
|
||||
|
||||
OpenNebula.log_error("do_unmap: #{err}") if rc != 0
|
||||
OpenNebula.log_error("#{__method__}: #{err}") if rc != 0
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class DiskRawMapper < Mapper
|
||||
|
||||
# Maps the whole file using kpartx. The output should be something like:
|
||||
# $ sudo kpartx -av /var/lib/one/datastores/100/0/disk.0
|
||||
# add map loop3p1 (253:0): 0 204800 linear 7:3 2048
|
||||
@ -63,8 +65,8 @@ class DiskRawMapper < Mapper
|
||||
rc, out, err = Command.execute(cmd, true)
|
||||
|
||||
if rc != 0 || out.empty?
|
||||
OpenNebula.log_error("do_map: #{err}")
|
||||
return nil
|
||||
OpenNebula.log_error("#{__method__}: #{err}")
|
||||
return
|
||||
end
|
||||
|
||||
loopdev = out.lines[0].match(/.*add map loop(\d+)p\d+.*/)
|
||||
@ -83,7 +85,8 @@ class DiskRawMapper < Mapper
|
||||
|
||||
return true if rc.zero?
|
||||
|
||||
OpenNebula.log_error("do_unmap: #{err}")
|
||||
OpenNebula.log_error("#{__method__}: #{err}")
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -30,6 +30,8 @@ class RBDMapper < Mapper
|
||||
def disk_source(vm_id, disk)
|
||||
src = disk['SOURCE']
|
||||
return "#{src}-#{vm_id}-#{disk['DISK_ID']}" if disk['CLONE'] == 'YES'
|
||||
|
||||
src
|
||||
end
|
||||
|
||||
def do_map(one_vm, disk, _directory)
|
||||
@ -41,18 +43,19 @@ class RBDMapper < Mapper
|
||||
|
||||
return out.chomp if rc.zero?
|
||||
|
||||
OpenNebula.log_error("do_map: #{err}")
|
||||
OpenNebula.log_error("#{__method__}: #{err}")
|
||||
nil
|
||||
end
|
||||
|
||||
def do_unmap(device, one_vm, disk, directory)
|
||||
def do_unmap(device, _one_vm, _disk, _directory)
|
||||
cmd = "#{COMMANDS[:rbd]} #{@ceph_user} unmap #{device}"
|
||||
|
||||
rc, _out, err = Command.execute(cmd, false)
|
||||
|
||||
return true if rc.zero?
|
||||
|
||||
OpenNebula.log_error("do_unmap: #{err}")
|
||||
OpenNebula.log_error("#{__method__}: #{err}")
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -29,12 +29,15 @@ class LXDConfiguration < Hash
|
||||
:datastore_location => '/var/lib/one/datastores'
|
||||
}
|
||||
|
||||
LXDRC = '../../etc/vmm/lxd/lxdrc'
|
||||
|
||||
def initialize
|
||||
replace(DEFAULT_CONFIGURATION)
|
||||
|
||||
begin
|
||||
merge!(YAML.load_file("#{__dir__}/../../etc/vmm/lxd/lxdrc"))
|
||||
rescue
|
||||
merge!(YAML.load_file("#{__dir__}/#{LXDRC}"))
|
||||
rescue => e
|
||||
OpenNebula.log_error e
|
||||
end
|
||||
end
|
||||
|
||||
@ -69,9 +72,6 @@ class OpenNebulaVM
|
||||
|
||||
return unless disk
|
||||
|
||||
@ds_path = get_dspath(disk)
|
||||
@sysds_path = "#{@ds_path}/#{@sysds_id}"
|
||||
|
||||
@rootfs_id = disk['DISK_ID']
|
||||
boot_order = @xml['//TEMPLATE/OS/BOOT']
|
||||
@rootfs_id = boot_order.split(',')[0][-1] unless boot_order.empty?
|
||||
@ -374,25 +374,6 @@ class OpenNebulaVM
|
||||
mapped
|
||||
end
|
||||
|
||||
# Returns the datastores BASE_PATH location
|
||||
def get_dspath(disk)
|
||||
source = disk['SOURCE']
|
||||
cut = "/#{disk['DATASTORE_ID']}/"
|
||||
result = source.split(cut)
|
||||
|
||||
if result.length == 2
|
||||
path = result[0]
|
||||
else
|
||||
path = ''
|
||||
0.upto(result.length - 2) do |i|
|
||||
path << "#{result[i]}/#{dsid}/"
|
||||
end
|
||||
|
||||
path = path[0..path.rindex(cut)]
|
||||
end
|
||||
|
||||
path.gsub('//', '/')
|
||||
end
|
||||
end
|
||||
|
||||
# This class abstracts the access to XML elements. It provides basic methods
|
||||
|
Loading…
x
Reference in New Issue
Block a user