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

Feature 1685: Add better checks, minor code refactor

This commit is contained in:
Daniel Clavijo Coca 2019-02-18 11:17:37 -06:00 committed by Ruben S. Montero
parent 93309d0c50
commit 565e0f3187
6 changed files with 105 additions and 83 deletions

View File

@ -96,6 +96,8 @@ class LXDClient
response = get("operations/#{operation_id}/wait#{timeout}")
raise LXDError, response if response['metadata']['status'] == 'Failure'
response
end
private

View File

@ -139,6 +139,7 @@ class Container
cmd = "#{Mapper::COMMANDS[:lsblk]} -J"
_rc, o, _e = Command.execute(cmd, false)
# TODO: Add extra mounts to raise
raise "Container rootfs still mounted \n#{o}" if o.include?(@rootfs_dir)
wait?(@client.delete("#{CONTAINERS}/#{name}"), wait, timeout)
@ -182,8 +183,13 @@ class Container
change_state(__method__, options)
end
def stop(options = {})
def stop(options = { :timeout => 120 })
change_state(__method__, options)
rescue StandardError => exception
raise exception unless exception.class == Net::ReadTimeout
OpenNebula.log_error "Timeout detected\n#{exception}\nForcing shutdown"
stop(:force => true)
end
def restart(options = {})
@ -402,7 +408,7 @@ class Container
options.update(:action => action)
response = @client.put("#{CONTAINERS}/#{name}/state", options)
wait?(response, options[:wait], options[:timeout])
status = wait?(response, options[:wait], options[:timeout])
@lxc = @client.get("#{CONTAINERS}/#{name}")['metadata']

View File

@ -92,7 +92,7 @@ class Mapper
# @param disk [XMLElement] with the disk data
# @param directory [String] where the disk has to be mounted
#
# @return nil
# @return nil
def do_unmap(device, one_vm, disk, directory)
OpenNebula.log_error("unmap function not implemented for #{self.class}")
return nil
@ -256,76 +256,21 @@ class Mapper
# @param partitions [Array] with partition device names
# @param path [String] to directory to mount the disk partitions
def mount(partitions, path)
# TODO: Unmap device if mount fails
# Single partition
# ----------------
return mount_dev(partitions[0]['path'], path) if partitions.size == 1
# Multiple partitions
# -------------------
rc = true
fstab = ''
fstab = find_fstab(partitions, path)
# Look for fstab and mount rootfs in path. First partition with
# a /etc/fstab file is used as rootfs and it is kept mounted
partitions.each do |p|
OpenNebula.log("Looking for fstab on #{p['path']}")
rc = mount_dev(p['path'], path)
return false if !rc
bin = COMMANDS[:catfstab]
bin = COMMANDS[:cat] unless path.include?('containers/one-')
cmd = "#{bin} #{path}/etc/fstab"
_rc, fstab, _e = Command.execute(cmd, false)
if fstab.empty?
return false unless umount_dev(p['path'])
next
end
OpenNebula.log("Found fstab on #{p['path']}")
break
end
if fstab.empty?
OpenNebula.log_error('No fstab file found')
if !fstab
# TODO: Unmap the device
return false
end
# Parse fstab contents & mount partitions
fstab.each_line do |l|
next if l.strip.chomp.empty?
next if l =~ /\s*#/
fs, mount_point, type, opts, dump, pass = l.split
if l =~ /^\s*LABEL=/ # disk by LABEL
value = fs.split("=").last.strip.chomp
key = 'label'
elsif l =~ /^\s*UUID=/ #disk by UUID
value = fs.split("=").last.strip.chomp
key = 'uuid'
else #disk by device - NOT SUPPORTED or other FS
next
end
next if %w[/ swap].include?(mount_point)
partitions.each { |p|
next if p[key] != value
rc = mount_dev(p['path'], path + mount_point)
return false if !rc
break
}
end
rc
parse_fstab(partitions, path, fstab)
end
# --------------------------------------------------------------------------
@ -349,8 +294,6 @@ class Mapper
rc, _out, err = Command.execute("#{COMMANDS[:mount]} #{dev} #{path}", true)
if rc != 0
return true if err.include?("unknown filesystem type 'swap'")
OpenNebula.log_error("mount_dev: #{err}")
return false
end
@ -436,10 +379,12 @@ class Mapper
false
end
# Extracts the partiton table from a device
def show_parts(device)
action_parts(device, '-s -av')
end
# Hides the partiton table from a device
def hide_parts(device)
action_parts(device, '-d')
end
@ -459,7 +404,7 @@ class Mapper
_rc, out, _err = Command.execute("#{COMMANDS[:lsblk]} -J", false)
if out.include?(path)
OpenNebula.log_error("mount_dev: Mount detected in #{path}")
OpenNebula.log_error("#{__method__}: Mount detected in #{path}")
return true
end
false
@ -480,4 +425,70 @@ class Mapper
false
end
# Look for fstab and mount rootfs in path. First partition with
# a /etc/fstab file is used as rootfs and it is kept mounted
def find_fstab(partitions, path)
fstab = ''
partitions.each do |p|
OpenNebula.log("Looking for fstab on #{p['path']}")
rc = mount_dev(p['path'], path)
next unless rc
bin = COMMANDS[:catfstab]
bin = COMMANDS[:cat] unless path.include?('containers/one-')
cmd = "#{bin} #{path}/etc/fstab"
_rc, fstab, _e = Command.execute(cmd, false)
if fstab.empty?
return false unless umount_dev(p['path'])
next
end
OpenNebula.log("Found fstab on #{p['path']}")
break
end
return fstab unless fstab.empty?
OpenNebula.log_error('No fstab file found')
false
end
# Parse fstab contents & mount partitions
def parse_fstab(partitions, path, fstab)
fstab.each_line do |l|
next if l.strip.chomp.empty?
next if l =~ /\s*#/
fs, mount_point, _type, _opts, _dump, _pass = l.split
if l =~ /^\s*LABEL=/ # disk by LABEL
value = fs.split('=').last.strip.chomp
key = 'label'
elsif l =~ /^\s*UUID=/ # disk by UUID
value = fs.split('=').last.strip.chomp
key = 'uuid'
else # disk by device - NOT SUPPORTED or other FS
next
end
next if %w[/ swap].include?(mount_point)
partitions.each {|p|
next if p[key] != value
return false unless mount_dev(p['path'], path + mount_point)
break
}
end
true
end
end

View File

@ -19,9 +19,10 @@ require 'yaml'
# This class reads and holds configuration attributes for the LXD driver
class LXDConfiguration < Hash
# TODO: Create lxdrc file from this hash to avoid duplicated config
DEFAULT_CONFIGURATION = {
:vnc => {
:command => '/bin/bash',
:command => '/bin/login',
:width => '800',
:height => '600',
:timeout => '300'
@ -183,7 +184,7 @@ class OpenNebulaVM
end
end
def get_context_disk()
def get_context_disk
@xml.element('//TEMPLATE/CONTEXT')
end
@ -376,15 +377,16 @@ class OpenNebulaVM
# Creates or closes a connection to a container rfb port depending on signal
def vnc_command(signal)
data = @xml.element('//TEMPLATE/GRAPHICS')
return unless data && data['PORT'] && data['TYPE'] && data['TYPE'].casecmp('vnc').zero?
return unless data && data['TYPE'].casecmp('vnc').zero?
pass = data['PASSWD']
pass = '-' unless pass && !pass.empty?
pass = '-' if pass.empty?
case signal
when 'start'
# TODO: Allow to set vnc command on VM template
command = @lxdrc[:vnc][:command]
command = data['COMMAND'] unless data['COMMAND'].empty?
"#{data['PORT']} #{pass} lxc exec #{@vm_name} #{command}\n"
when 'stop'
"-#{data['PORT']}\n"

View File

@ -71,16 +71,21 @@ else
mapped = container.setup_storage('map')
raise 'failed to setup container storage' unless mapped
if container.start != 'Running'
OpenNebula.log_error('Container failed to start')
begin
operation = container.start
raise operation if container.status != 'Running'
rescue LXDError => exception
storage_deleted = container.setup_storage('unmap')
deleted = container.setup_storage('unmap')
raise 'failed to dismantle container storage' unless deleted
if storage_deleted
container.delete
else
OpenNebula.log_error 'failed to dismantle container storage'
end
container.delete
raise LXDError, container.status
raise LXDError, exception
end
end
#-------------------------------------------------------------------------------

View File

@ -44,13 +44,9 @@ end
if !container.wild?
unmapped = container.setup_storage('unmap')
unless unmapped
container.start
raise 'Failed to dismantle container storage'
end
raise 'Failed to dismantle container storage' unless unmapped
container.delete
end
container.vnc('stop')