1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-22 18:50:08 +03:00

F #1684: Discover LXD installation paths, other minor updates

This commit is contained in:
Daniel Clavijo Coca 2018-12-13 04:14:06 -06:00 committed by Ruben S. Montero
parent d9fb25db65
commit 48664d4c57
6 changed files with 121 additions and 79 deletions

View File

@ -31,14 +31,25 @@ class LXDClient
API = '/1.0'.freeze
HEADER = { 'Host' => 'localhost' }.freeze
SOCK_PATH = '/var/lib/lxd/unix.socket'
attr_reader :lxd_path
# Enable communication with LXD via unix socket
begin
SOCK = Net::BufferedIO.new(UNIXSocket.new(SOCK_PATH))
rescue StandardError
STDERR.puts('Could not open LXD socket')
Process.exit(1)
def initialize
paths = ['/var/lib/lxd', '/var/snap/lxd/common/lxd']
@socket = nil
@lxd_path = nil
paths.each do |path|
begin
@socket = socket(path)
@lxd_path = path
break
rescue
next
end
end
raise 'Failed to open LXD socket' unless @socket
end
# Performs HTTP::Get
@ -89,6 +100,11 @@ class LXDClient
private
# Enable communication with LXD via unix socket
def socket(lxd_path)
Net::BufferedIO.new(UNIXSocket.new("#{lxd_path}/unix.socket"))
end
# Returns the HTTPResponse body as a hash
# Params:
# +request+:: +Net::HTTP::Request+ made to the http server
@ -98,16 +114,16 @@ class LXDClient
def get_response(request, data)
request.body = JSON.dump(data) unless data.nil?
request.exec(SOCK, '1.1', request.path)
request.exec(@socket, '1.1', request.path)
response = nil
loop do
response = Net::HTTPResponse.read_new(SOCK)
response = Net::HTTPResponse.read_new(@socket)
break unless response.is_a?(Net::HTTPContinue)
end
response.reading_body(SOCK, request.response_body_permitted?) {}
response.reading_body(@socket, request.response_body_permitted?) {}
response = JSON.parse(response.body)

View File

@ -68,53 +68,58 @@ class Container
@lxc = lxc
@one = one
@containers = "#{@client.lxd_path}/storage-pools/default/containers"
@rootfs_dir = "#{@containers}/#{name}/rootfs"
@context_path = "#{@rootfs_dir}/context"
end
class << self
# Returns specific container, by its name
# Params:
# +name+:: container name
def get(name, one_xml, client)
info = client.get("#{CONTAINERS}/#{name}")['metadata']
# Returns specific container, by its name
# Params:
# +name+:: container name
def get(name, one_xml, client)
info = client.get("#{CONTAINERS}/#{name}")['metadata']
one = nil
one = OpenNebulaVM.new(one_xml) if one_xml
one = nil
one = OpenNebulaVM.new(one_xml) if one_xml
Container.new(info, one, client)
rescue LXDError => exception
raise exception
end
# Creates container from a OpenNebula VM xml description
def new_from_xml(one_xml, client)
one = OpenNebulaVM.new(one_xml)
Container.new(one.to_lxc, one, client)
end
# Returns an array of container objects
def get_all(client)
containers = []
container_names = client.get(CONTAINERS)['metadata']
container_names.each do |name|
name = name.split('/').last
containers.push(get(name, nil, client))
Container.new(info, one, client)
rescue LXDError => exception
raise exception
end
containers
end
# Creates container from a OpenNebula VM xml description
def new_from_xml(one_xml, client)
one = OpenNebulaVM.new(one_xml)
# Returns boolean indicating if the container exists(true) or not (false)
def exist?(name, client)
client.get("#{CONTAINERS}/#{name}")
true
rescue LXDError => exception
raise exception if exception.body['error_code'] != 404
Container.new(one.to_lxc, one, client)
end
false
end
# Returns an array of container objects
def get_all(client)
containers = []
container_names = client.get(CONTAINERS)['metadata']
container_names.each do |name|
name = name.split('/').last
containers.push(get(name, nil, client))
end
containers
end
# Returns boolean indicating if the container exists(true) or not (false)
def exist?(name, client)
client.get("#{CONTAINERS}/#{name}")
true
rescue LXDError => exception
raise exception if exception.body['error_code'] != 404
false
end
end
@ -131,6 +136,10 @@ class Container
# Delete container
def delete(wait: true, timeout: '')
unless Dir.empty?(@rootfs_dir) || (Dir["#{@rootfs_dir}/*"] == [@context_path] && Dir.empty?(@context_path))
raise 'Container rootfs not empty'
end
wait?(@client.delete("#{CONTAINERS}/#{name}"), wait, timeout)
end
@ -222,8 +231,7 @@ class Container
context = @one.get_context_disk
mapper = FSRawMapper.new
context_path = "#{@one.lxdrc[:containers]}/#{name}/rootfs/context"
create_context_dir = "#{Mapper::COMMANDS[:su_mkdir]} #{context_path}"
create_context_dir = "#{Mapper::COMMANDS[:su_mkdir]} #{@context_path}"
rc, _o, e = Command.execute(create_context_dir, false)
@ -330,7 +338,7 @@ class Container
disk_id = disk['DISK_ID']
if disk_id == @one.rootfs_id
target = "#{@one.lxdrc[:containers]}/#{name}/rootfs"
target = @rootfs_dir
else
target = @one.disk_mountpoint(disk_id)
end

View File

@ -190,19 +190,19 @@ class Mapper
device = ''
real_path = directory
ds = one_vm.lxdrc[:datastore_location] + "/#{one_vm.sysds_id}"
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)
end
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']
@ -213,13 +213,18 @@ class Mapper
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}")
return
end
return unless umount(partitions)
return unless do_unmap(device, one_vm, disk, real_path)
@ -330,6 +335,18 @@ class Mapper
def mount_dev(dev, path)
OpenNebula.log_info "Mounting #{dev} at #{path}"
rc, out, err = Command.execute("#{COMMANDS[:lsblk]} -J", false)
if rc != 0 || out.empty?
OpenNebula.log_error("mount_dev: #{err}")
return false
end
if out.match?(path)
OpenNebula.log_error("mount_dev: Mount detected in #{path}")
return false
end
if path =~ /.*\/rootfs/
cmd = COMMANDS[:su_mkdir]
else

View File

@ -33,8 +33,7 @@ class Qcow2Mapper < Mapper
dsrc = disk_source(one_vm, disk)
cmd = "#{COMMANDS[:nbd]} -c #{device} #{dsrc}"
ds = one_vm.lxdrc[:datastore_location] + "/#{one_vm.sysds_id}"
File.chmod(0664, dsrc) if File.symlink?(ds)
File.chmod(0664, dsrc) if File.symlink?(one_vm.sysds_path)
rc, _out, err = Command.execute(cmd, true)

View File

@ -25,9 +25,7 @@ class LXDConfiguration < Hash
:width => '800',
:height => '600',
:timeout => '300'
},
:datastore_location => '/var/lib/one/datastores',
:containers => '/var/lib/lxd/storage-pools/default/containers'
}
}
def initialize
@ -44,7 +42,7 @@ end
# This class parses and wraps the information in the Driver action data
class OpenNebulaVM
attr_reader :xml, :vm_id, :vm_name, :sysds_id, :ds_path, :rootfs_id, :lxdrc
attr_reader :xml, :vm_id, :vm_name, :sysds_id, :ds_path, :rootfs_id, :lxdrc, :sysds_path
#---------------------------------------------------------------------------
# Class Constructor
@ -64,13 +62,14 @@ class OpenNebulaVM
# Load Driver configuration
@lxdrc = LXDConfiguration.new
@ds_path = @lxdrc[:datastore_location]
# Sets the DISK ID of the root filesystem
disk = @xml.element('//TEMPLATE/DISK')
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?
@ -373,6 +372,25 @@ 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

View File

@ -27,20 +27,4 @@
:command: /bin/bash
:width: 800
:height: 600
:timeout: 300
################################################################################
# OpenNebula Configuration Options
################################################################################
#
# Default path for the datastores. This only need to be change if the
# corresponding value in oned.conf has been modified.
:datastore_location: /var/lib/one/datastores
################################################################################
# LXD Options
################################################################################
#
# Path to containers location to mount the root file systems
:containers: /var/lib/lxd/storage-pools/default/containers
:timeout: 300