diff --git a/include/LibVirtDriver.h b/include/LibVirtDriver.h new file mode 100644 index 0000000000..62da630310 --- /dev/null +++ b/include/LibVirtDriver.h @@ -0,0 +1,35 @@ +#ifndef LIBVIRT_DRIVER_H_ +#define LIBVIRT_DRIVER_H_ + +#include +#include +#include + +#include "VirtualMachineManagerDriver.h" + +class LibVirtDriver : public VirtualMachineManagerDriver +{ +public: + + LibVirtDriver( + int userid, + const map &attrs, + bool sudo, + VirtualMachinePool * pool, + const string _emulator): + VirtualMachineManagerDriver(userid, attrs,sudo,pool), + emulator(_emulator) + {}; + + ~LibVirtDriver(){}; + +private: + int deployment_description( + const VirtualMachine * vm, + const string& file_name) const; + + const string emulator; +}; + +#endif /*LIBVIRT_DRIVER_H_*/ + diff --git a/install.sh b/install.sh index cda31799cf..3d37b69f72 100755 --- a/install.sh +++ b/install.sh @@ -34,19 +34,25 @@ inst_cp share/etc/oned.conf etc inst_ln share/etc/mad/defaultrc etc/mad inst_ln share/etc/mad/im_sshrc etc/mad inst_ln share/etc/mad/vmm_xenrc etc/mad +inst_ln share/etc/mad/vmm_kvmrc etc/mad inst_ln share/etc/default/vmm_xen.conf etc/default +inst_ln share/etc/default/vmm_kvm.conf etc/default inst_ln share/scripts/madcommon.sh libexec inst_ln src/vmm_mad/xen/one_vmm_xen.rb bin inst_ln src/vmm_mad/xen/one_vmm_xen bin -inst_ln src/im_mad/xen/one_im_ssh.rb bin -inst_ln src/im_mad/xen/one_im_ssh bin +inst_ln src/vmm_mad/kvm_ssh/one_vmm_kvm.rb bin +inst_ln src/vmm_mad/kvm_ssh/one_vmm_kvm bin -inst_cp src/im_mad/xen/one_im_ssh.conf etc/default -inst_ln src/vmm_mad/xen/one_mad.rb lib/ruby +inst_ln src/im_mad/im_ssh/one_im_ssh.rb bin +inst_ln src/im_mad/im_ssh/one_im_ssh bin + +inst_cp src/im_mad/xen/im_xen.conf etc +inst_cp src/im_mad/kvm/im_kvm.conf etc inst_ln src/im_mad/xen/one_ssh.rb lib/ruby +inst_ln src/vmm_mad/xen/one_mad.rb lib/ruby inst_ln src/client/ruby/one.rb lib/ruby inst_ln src/client/ruby/client_utilities.rb lib/ruby inst_ln src/client/ruby/command_parse.rb lib/ruby diff --git a/share/etc/default/vmm_kvm.conf b/share/etc/default/vmm_kvm.conf new file mode 100644 index 0000000000..162f4c9290 --- /dev/null +++ b/share/etc/default/vmm_kvm.conf @@ -0,0 +1,5 @@ +# +# Default configuration attributes for the KVM driver +# (all domains will use these values as defaults) +# + diff --git a/share/etc/mad/vmm_kvmrc b/share/etc/mad/vmm_kvmrc new file mode 100644 index 0000000000..d67a4d43e6 --- /dev/null +++ b/share/etc/mad/vmm_kvmrc @@ -0,0 +1,17 @@ +# -------------------------------------------------------------------------- # +# Copyright 2002-2008, Distributed Systems Architecture Group, Universidad # +# Complutense de Madrid (dsa-research.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + diff --git a/share/etc/oned.conf b/share/etc/oned.conf index 77293e0ea8..eeb5da454e 100644 --- a/share/etc/oned.conf +++ b/share/etc/oned.conf @@ -9,8 +9,10 @@ # HOST_MONITORING_INTERVAL: Time in seconds between host monitorization # VM_POLLING_INTERVAL: Time in seconds between virtual machine monitorization # -# VM_RDIR: Path to access $ONE_LOCATION/var/ on the remote nodes. Only needed -# if this path is different in the nodes and in the frontend. +# VM_RDIR: The remote nodes must have access to $ONE_LOCATION/var, so this must +# be shared between the ONE server and the remote nodes. If the mount point of +# $ONE_LOCATION/var has a different path in the remote nodes than in the ONE server, +# set here the mount point of the _remote_ nodes # # PORT: Port where oned will listen for xmlrpc calls. # @@ -39,10 +41,20 @@ DEBUG_LEVEL=3 #------------------------------------------------------------------------------- IM_MAD = [ - name = "one_im", + name = "im_xen", executable = "bin/one_im_ssh", - arguments = "etc/default/one_im_ssh.conf", - default = "etc/default/one_im_ssh.conf" ] + arguments = "etc/default/im_xen.conf", + default = "etc/default/im_xen.conf" ] + + #------------------------------------------------------------------------------- + # KVM Information Driver Manager sample configuration + #------------------------------------------------------------------------------- + # VM_MAD = [ + # name = "im_kvm", + # executable = "bin/one_im_ssh", + # arguments = "etc/default/im_kvm.conf", + # default = "etc/default/im_kvm.conf" ] + #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- # Virtualization Driver Configuration @@ -58,8 +70,21 @@ IM_MAD = [ #------------------------------------------------------------------------------- VM_MAD = [ - name = "one_vmm", + name = "vmm_xen", executable = "bin/one_vmm_xen", default = "etc/default/vmm_xen.conf", type = "xen" ] + #------------------------------------------------------------------------------- + # KVM Virtualization Driver Manager sample configuration + #------------------------------------------------------------------------------- + # VM_MAD = [ + # name = "vmm_kvm", + # executable = "bin/one_vmm_kvm", + # default = "etc/default/kvm_xen.conf", + # type = "kvm" ] + #------------------------------------------------------------------------------- + + + + diff --git a/src/im_mad/xen/architecture.sh b/src/im_mad/im_ssh/architecture.sh similarity index 100% rename from src/im_mad/xen/architecture.sh rename to src/im_mad/im_ssh/architecture.sh diff --git a/src/im_mad/xen/cpu.sh b/src/im_mad/im_ssh/cpu.sh similarity index 100% rename from src/im_mad/xen/cpu.sh rename to src/im_mad/im_ssh/cpu.sh diff --git a/src/im_mad/xen/name.sh b/src/im_mad/im_ssh/name.sh similarity index 100% rename from src/im_mad/xen/name.sh rename to src/im_mad/im_ssh/name.sh diff --git a/src/im_mad/xen/one_im_ssh b/src/im_mad/im_ssh/one_im_ssh similarity index 100% rename from src/im_mad/xen/one_im_ssh rename to src/im_mad/im_ssh/one_im_ssh diff --git a/src/im_mad/xen/one_im_ssh.rb b/src/im_mad/im_ssh/one_im_ssh.rb similarity index 100% rename from src/im_mad/xen/one_im_ssh.rb rename to src/im_mad/im_ssh/one_im_ssh.rb diff --git a/src/im_mad/xen/one_ssh.rb b/src/im_mad/im_ssh/one_ssh.rb similarity index 100% rename from src/im_mad/xen/one_ssh.rb rename to src/im_mad/im_ssh/one_ssh.rb diff --git a/src/im_mad/kvm/im_kvm.conf b/src/im_mad/kvm/im_kvm.conf new file mode 100644 index 0000000000..8394556bf3 --- /dev/null +++ b/src/im_mad/kvm/im_kvm.conf @@ -0,0 +1,8 @@ + +# Remote directory where scripts are written +REMOTE_DIR=/tmp/ne_im_scripts + +cpuarchitecture=lib/im_probes/architecture.sh +nodename=lib/im_probes/name.sh +cpu=lib/im_probes/cpu.sh +kvm=lib/im_probes/kvm.rb diff --git a/src/im_mad/kvm/kvm.rb b/src/im_mad/kvm/kvm.rb new file mode 100755 index 0000000000..3a86fd5751 --- /dev/null +++ b/src/im_mad/kvm/kvm.rb @@ -0,0 +1,77 @@ +#!/usr/bin/env ruby + +###### +# First, get all the posible info out of virsh +# TODO : use virsh freecell when available +###### + +nodeinfo_text = `virsh nodeinfo` + +nodeinfo_text.split(/\n/).each{|line| + if line.match('^CPU\(s\)') + $total_cpu = line.split(":")[1].strip.to_i * 100 + elsif line.match('^CPU frequency') + $cpu_speed = line.split(":")[1].strip.split(" ")[0] + elsif line.match('^Memory size') + $total_memory = line.split(":")[1].strip.split(" ")[0] + end +} + +###### +# for everything else, top & proc +##### + +NETINTERFACE = "eth1" + +top_text=`top -bin2` +top_text.gsub!(/^top.*^top.*?$/m, "") # Strip first top output + +top_text.split(/\n/).each{|line| + if line.match('^Mem') + line[4..-1].split(",").each{|elemento| + temp = elemento.strip.split("k ") + if temp[1] == "used" + $used_memory = temp[0] + elsif temp[1] == "free" + $free_memory = temp[0] + end + } + + elsif line.match('^Cpu') + line[7..-1].split(",").each{|elemento| + temp = elemento.strip.split("%") + if temp[1]=="id" + $free_cpu = temp[0] + used = temp[0].to_f + $used_cpu = (((100 - used)*100).round / 100).to_f.to_s + break + end + + } + end +} + +net_text=`cat /proc/net/dev` + +net_text.split(/\n/).each{|line| + if line.match("^ *#{NETINTERFACE}") + arr = line.split(":")[1].split(" ") + $netrx = arr[0] + $nettx = arr[8] + break + end +} + +puts "TOTALCPU=#{$total_cpu}" +puts "CPUSPEED=#{$cpu_speed}" + +puts "TOTALMEMORY=#{$total_memory}" +puts "USEDMEMORY=#{$used_memory}" +puts "FREEMEMORY=#{$free_memory}" + +puts "FREECPU=#{$free_cpu}" +puts "USEDCPU=#{$used_cpu}" + +puts "NETRX=#{$netrx}" +puts "NETTX=#{$nettx}" + diff --git a/src/im_mad/xen/one_im_ssh.conf b/src/im_mad/xen/im_xen.conf similarity index 100% rename from src/im_mad/xen/one_im_ssh.conf rename to src/im_mad/xen/im_xen.conf diff --git a/src/vmm/LibVirtDriver.cc b/src/vmm/LibVirtDriver.cc new file mode 100644 index 0000000000..2f415617f7 --- /dev/null +++ b/src/vmm/LibVirtDriver.cc @@ -0,0 +1,36 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2008, Distributed Systems Architecture Group, Universidad */ +/* Complutense de Madrid (dsa-research.org) */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); you may */ +/* not use this file except in compliance with the License. You may obtain */ +/* a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* -------------------------------------------------------------------------- */ + +#include "LibVirtDriver.h" + +#include "Nebula.h" +#include +#include + +int LibVirtDriver::deployment_description( + const VirtualMachine * vm, + const string& file_name) const +{ + + ostringstream oss; + + oss << "cp /home/tinova/kvmxml.tmpl " << file_name ; + + system(oss.str().c_str()); + + return 0; +} diff --git a/src/vmm/SConstruct b/src/vmm/SConstruct index db70d99984..6457d1d8a1 100644 --- a/src/vmm/SConstruct +++ b/src/vmm/SConstruct @@ -9,6 +9,7 @@ source_files=[ 'VirtualMachineManager.cc', 'VirtualMachineManagerDriver.cc', 'XenDriver.cc', + 'LibVirtDriver.cc', ] # Build library diff --git a/src/vmm/VirtualMachineManager.cc b/src/vmm/VirtualMachineManager.cc index c38a01782a..5901d572b6 100644 --- a/src/vmm/VirtualMachineManager.cc +++ b/src/vmm/VirtualMachineManager.cc @@ -18,6 +18,7 @@ #include "VirtualMachineManager.h" #include "Nebula.h" #include "XenDriver.h" +#include "LibVirtDriver.h" #include /* ************************************************************************** */ @@ -787,7 +788,7 @@ void VirtualMachineManager::load_mads(int uid) } else if ( type == "KVM" ) { - vmm_driver = new KvmDriver(uid, vattr->value(),(uid != 0),vmpool); + vmm_driver = new LibVirtDriver(uid, vattr->value(),(uid != 0),vmpool,"kvm"); } else { diff --git a/src/vmm_mad/kvm_ssh/one_vmm_kvm b/src/vmm_mad/kvm_ssh/one_vmm_kvm new file mode 100755 index 0000000000..994c1ee665 --- /dev/null +++ b/src/vmm_mad/kvm_ssh/one_vmm_kvm @@ -0,0 +1,17 @@ +#!/bin/bash + +if [ -z "${ONE_LOCATION}" ]; then + echo "Please, set ONE_LOCATION variable." + exit -1 +fi + +. $ONE_LOCATION/libexec/madcommon.sh + +# Export the vmm_mad specific rc +export_rc_vars $ONE_LOCATION/etc/mad/vmm_kvmrc + +# Go to ONE_LOCATION +cd $ONE_LOCATION + +# Execute the actual MAD +execute_mad $* \ No newline at end of file diff --git a/src/vmm_mad/kvm_ssh/one_vmm_kvm.rb b/src/vmm_mad/kvm_ssh/one_vmm_kvm.rb new file mode 100755 index 0000000000..b459a7b85a --- /dev/null +++ b/src/vmm_mad/kvm_ssh/one_vmm_kvm.rb @@ -0,0 +1,174 @@ +#!/usr/bin/env ruby + +ONE_LOCATION=ENV["ONE_LOCATION"] + +if !ONE_LOCATION + puts "ONE_LOCATION not set" + exit -1 +end + +$: << ONE_LOCATION+"/lib/ruby" + +require 'pp' + +require 'one_mad' +require 'open3' + + +class DM < ONEMad + + def initialize + super(5, 4) + end + + def action_init(args) + send_message("INIT", "SUCCESS") + log("KVM Access Driver initialized.") + end + + def action_deploy(args) + std_action("DEPLOY", "create #{args[3]}", args) + end + + def action_shutdown(args) + std_action("SHUTDOWN", "shutdown #{args[3]}", args) + end + + def action_cancel(args) + std_action("CANCEL", "destroy #{args[3]}", args) + end + + def action_checkpoint(args) + send_message("CHECKPOINT", "FAILURE", args[1], "action not supported for KVM") + end + + def action_save(args) + std_action("SAVE", "save #{args[3]} #{args[4]}", args) + end + + def action_restore(args) + std_action("RESTORE", "restore #{args[3]}", args) + end + + def action_migrate(args) + send_message("MIGRATE", "FAILURE", args[1], "action not supported for KVM") + end + + def action_poll(args) + + std=Open3.popen3( + "ssh -n #{args[2]} virsh dominfo #{args[3]};"+ + " echo ExitCode: $? 1>&2") + stdout=std[1].read + stderr=std[2].read + + exit_code=get_exit_code(stderr) + + if exit_code!=0 + send_message("POLL", "FAILURE", args[1]) + return nil + end + + log("stdout:") + log(stdout) + log("stderr:") + log(stderr) + + info = parse_virsh_dominfo(stdout) + + # TODO -> Get more info, like NET info. Need to know the iface name (e.g. tap0) + + send_message("POLL", "SUCCESS", args[1], info) + end + + ########################### + # Common action functions # + ########################### + + def std_action(name, command, args) + std=exec_kvm_command(args[2], command) + stdout=std[1].read + stderr=std[2].read + + + + log("stdout:") + log(stdout) + log("stderr:") + log(stderr) + + write_response(name, stdout, stderr, args) + end + + def exec_kvm_command(host, command) + Open3.popen3( + "ssh -n #{host} virsh #{command} ;"+ + " echo ExitCode: $? 1>&2") + end + + def write_response(action, stdout, stderr, args) + exit_code=get_exit_code(stderr) + + if exit_code==0 + domain_name=get_domain_name(stdout) + send_message(action, "SUCCESS", args[1], domain_name) + else + error_message=get_error_message(stderr) + send_message(action, "FAILURE", args[1], error_message) + end + + end + + + ######################################### + # Get information from virsh # + ######################################### + + # From STDERR if exit code == 1 + def get_exit_code(str) + tmp=str.scan(/^ExitCode: (\d*)$/) + return nil if !tmp[0] + tmp[0][0].to_i + end + + # From STDERR if exit code == 1 + def get_error_message(str) + tmp=str.scan(/^Error: (.*)$/) + return "Unknown error" if !tmp[0] + tmp[0][0] + end + + # From STDOUT if exit code == 0 + def get_domain_name(str) + tmp=str.scan(/^Domain (.*) created from .*$/) + return nil if !tmp[0] + tmp[0][0] + end + + + ############################### + # Get information from virsh # + ############################### + + + def parse_virsh_dominfo(returned_info) + + info = "" + + returned_info.each_line {|line| + + columns=line.split(":").collect {|c| c.strip } + case columns[0] + when 'Used memory' + info += "USEDMEMORY=" + columns[1].to_i*1024 + + end + } + + return info + end + +end + +dm=DM.new +dm.loop