diff --git a/install.sh b/install.sh index da629029a0..048ef1b526 100755 --- a/install.sh +++ b/install.sh @@ -528,7 +528,6 @@ RUBY_LIB_FILES="src/mad/ruby/ActionManager.rb \ src/mad/ruby/ssh_stream.rb \ src/vnm_mad/one_vnm.rb \ src/mad/ruby/Ganglia.rb \ - src/mad/ruby/vmwarelib.rb \ src/oca/ruby/OpenNebula.rb \ src/tm_mad/TMScript.rb \ src/authm_mad/remotes/ssh/ssh_auth.rb \ @@ -616,10 +615,12 @@ VMM_EXEC_VMWARE_SCRIPTS="src/vmm_mad/remotes/vmware/cancel \ src/vmm_mad/remotes/vmware/deploy \ src/vmm_mad/remotes/vmware/migrate \ src/vmm_mad/remotes/vmware/restore \ + src/vmm_mad/remotes/vmware/reboot \ src/vmm_mad/remotes/vmware/save \ src/vmm_mad/remotes/vmware/poll \ src/vmm_mad/remotes/vmware/checkpoint \ - src/vmm_mad/remotes/vmware/shutdown" + src/vmm_mad/remotes/vmware/shutdown \ + src/vmm_mad/remotes/vmware/vmware_driver.rb" #------------------------------------------------------------------------------- # Information Manager Probes, to be installed under $REMOTES_LOCATION/im @@ -729,7 +730,9 @@ LVM_TM_COMMANDS_LIB_FILES="src/tm_mad/lvm/tm_clone.sh \ VMWARE_TM_COMMANDS_LIB_FILES="src/tm_mad/vmware/tm_clone.sh \ src/tm_mad/vmware/tm_ln.sh \ - src/tm_mad/vmware/tm_mv.sh" + src/tm_mad/vmware/tm_mv.sh \ + src/tm_mad/vmware/functions.sh \ + src/tm_mad/vmware/tm_context.sh" #------------------------------------------------------------------------------- # Image Repository drivers, to be installed under $REMOTES_LOCATION/image diff --git a/src/im_mad/remotes/vmware.d/vmware.rb b/src/im_mad/remotes/vmware.d/vmware.rb index 5552818cf3..b4c061656c 100755 --- a/src/im_mad/remotes/vmware.d/vmware.rb +++ b/src/im_mad/remotes/vmware.d/vmware.rb @@ -16,18 +16,31 @@ # limitations under the License. # # ---------------------------------------------------------------------------- # -ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION) +ONE_LOCATION=ENV["ONE_LOCATION"] if !ONE_LOCATION - ETC_LOCATION = "/etc/one" if !defined?(ETC_LOCATION) - RUBY_LIB_LOCATION = "/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION) + BIN_LOCATION = "/usr/bin" + LIB_LOCATION = "/usr/lib/one" + ETC_LOCATION = "/etc/one/" + VAR_LOCATION = "/var/lib/one" + RUBY_LIB_LOCATION = "/usr/lib/one/ruby" else - ETC_LOCATION = ONE_LOCATION+"/etc" if !defined?(ETC_LOCATION) - RUBY_LIB_LOCATION = ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION) + LIB_LOCATION = ONE_LOCATION + "/lib" + BIN_LOCATION = ONE_LOCATION + "/bin" + ETC_LOCATION = ONE_LOCATION + "/etc/" + VAR_LOCATION = ONE_LOCATION + "/var/" + RUBY_LIB_LOCATION = ONE_LOCATION+"/lib/ruby" end $: << RUBY_LIB_LOCATION +CONF_FILE = ETC_LOCATION + "/vmwarerc" + +ENV['LANG'] = 'C' + +require "scripts_common" +require 'yaml' +require "CommandManager" require 'OpenNebula' include OpenNebula @@ -38,6 +51,30 @@ rescue Exception => e exit(-1) end +# ######################################################################## # +# DRIVER HELPER FUNCTIONS # +# ######################################################################## # + +#Generates an ESX command using ttyexpect +def esx_cmd(command) + cmd = "#{BIN_LOCATION}/tty_expect -u #{@user} -p #{@pass} #{command}" +end + +#Performs a action usgin libvirt +def do_action(cmd) + rc = LocalCommand.run(esx_cmd(cmd)) + + if rc.code == 0 + return [true, rc.stdout] + else + err = "Error executing: #{cmd} err: #{rc.stderr} out: #{rc.stdout}" + OpenNebula.log_error(err) + return [false, rc.code] + end +end + +@result_str = "" + def add_info(name, value) value = "0" if value.nil? or value.to_s.empty? @result_str << "#{name}=#{value} " @@ -47,23 +84,31 @@ def print_info puts @result_str end -@result_str = "" +# ######################################################################## # +# Main Procedure # +# ######################################################################## # -@host = ARGV[2] +host = ARGV[2] -if !@host +if !host exit -1 end -load ETC_LOCATION + "/vmwarerc" +conf = YAML::load(File.read(CONF_FILE)) -if USERNAME.class!=String || PASSWORD.class!=String - warn "Bad ESX credentials, aborting" - exit -1 +@uri = conf[:libvirt_uri].gsub!('@HOST@', host) + +@user = conf[:username] +@pass = conf[:password] + +# Poll the VMware hypervisor + +rc, data = do_action("virsh -c #{@uri} --readonly nodeinfo") + +if rc == false + exit info end -data = perform_action("virsh -c #{LIBVIRT_URI} --readonly nodeinfo") - data.split(/\n/).each{|line| if line.match('^CPU\(s\)') $total_cpu = line.split(":")[1].strip.to_i * 100 diff --git a/src/image_mad/remotes/fs/cp b/src/image_mad/remotes/fs/cp index bbb2a67783..f1a557eb63 100755 --- a/src/image_mad/remotes/fs/cp +++ b/src/image_mad/remotes/fs/cp @@ -61,6 +61,11 @@ vmware://*) exec_and_log "cp -rf $SRC $DST" \ "Error copying $SRC to $DST" + + BASE_DISK_FILE=`ls $DST | grep -v '.*-s[0-9]*\.vmdk'` + + exec_and_log "mv -f $DST/$BASE_DISK_FILE $DST/disk.vmdk" \ + "Error renaming disk file $BASE_DISK_FILE to disk.vmdk" exec_and_log "chmod 0770 $DST" ;; @@ -86,4 +91,4 @@ esac SIZE=`fs_du $DST` -echo "$DST $SIZE" \ No newline at end of file +echo "$DST $SIZE" diff --git a/src/image_mad/remotes/fs/fsrc b/src/image_mad/remotes/fs/fsrc index 8cec0f0b05..4df7a005a3 100644 --- a/src/image_mad/remotes/fs/fsrc +++ b/src/image_mad/remotes/fs/fsrc @@ -92,12 +92,3 @@ function check_restricted { echo 0 } - -# Change the permissions of all the files inside directoriers (= VMware disks) -function fix_owner_perms { - find $IMAGE_REPOSITORY_PATH -type d \ - -mindepth 1 \ - -maxdepth 1 \ - -execdir chown \ - -R $SUDO_USER '{}' \; -} \ No newline at end of file diff --git a/src/image_mad/remotes/fs/mv b/src/image_mad/remotes/fs/mv index 84c845803e..02290af989 100755 --- a/src/image_mad/remotes/fs/mv +++ b/src/image_mad/remotes/fs/mv @@ -53,7 +53,9 @@ http://*) *) log "Moving local image $SRC to the image repository" - if [ \( -L $SRC \) -a \( "`$READLINK $SRC`" = "$DST" \) ] ; then + + if [ \( -L $SRC \) -a \ + \( "`$READLINK -f $SRC`" = "`$READLINK -f $DST`" \) ] ; then log "Not moving files to image repo, they are the same" else exec_and_log "mv -f $SRC $DST" "Could not move $SRC to $DST" @@ -63,7 +65,6 @@ esac if [ -d $DST ]; then exec_and_log "chmod 0770 $DST" - fix_owner_perms else exec_and_log "chmod 0660 $DST" fi diff --git a/src/mad/ruby/scripts_common.rb b/src/mad/ruby/scripts_common.rb index 8251ae48ff..8ded7d72cb 100644 --- a/src/mad/ruby/scripts_common.rb +++ b/src/mad/ruby/scripts_common.rb @@ -46,7 +46,7 @@ module OpenNebula STDERR.puts format_error_message(message) end - #This function formats an error message for OpenNebula Copyright e + #This function formats an error message for OpenNebula def self.format_error_message(message) error_str = "ERROR MESSAGE --8<------\n" error_str << message diff --git a/src/mad/ruby/vmwarelib.rb b/src/mad/ruby/vmwarelib.rb deleted file mode 100644 index a763e7f660..0000000000 --- a/src/mad/ruby/vmwarelib.rb +++ /dev/null @@ -1,60 +0,0 @@ -# ---------------------------------------------------------------------------- # -# Copyright 2010-2011, C12G Labs S.L # -# # -# 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. # -# ---------------------------------------------------------------------------- # - -# ---------------------------------------------------------------------------- # -# Set up the environment for the driver # -# ---------------------------------------------------------------------------- # - -ONE_LOCATION = ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION) - -if !ONE_LOCATION - BIN_LOCATION = "/usr/bin" if !defined?(BIN_LOCATION) - ETC_LOCATION = "/etc/one/" if !defined?(ETC_LOCATION) - RUBY_LIB_LOCATION = "/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION) -else - BIN_LOCATION = ONE_LOCATION + "/bin" if !defined?(BIN_LOCATION) - ETC_LOCATION = ONE_LOCATION + "/etc/" if !defined?(ETC_LOCATION) - if !defined?(RUBY_LIB_LOCATION) - RUBY_LIB_LOCATION = ONE_LOCATION + "/lib/ruby" - end -end - -$: << RUBY_LIB_LOCATION - -require "OpenNebulaDriver" -require "CommandManager" - -# Do host sustitution in the libvirt URI -LIBVIRT_URI.gsub!('@HOST@', @host) - -# Common functions -def perform_action(command) - command = BIN_LOCATION + "/tty_expect -u " + USERNAME + " -p " + PASSWORD + " " + command - - action_result = LocalCommand.run(command) - - if action_result.code == 0 - return action_result.stdout - else - log(command, action_result.stderr, action_result.stdout) - return action_result.code - end -end - -def log(cmd, stdout, stderr) - STDERR.puts "[VMWARE] cmd failed [" + cmd + - "]. Stderr: " + stderr + ". Stdout: " + stdout -end diff --git a/src/tm_mad/vmware/functions.sh b/src/tm_mad/vmware/functions.sh new file mode 100644 index 0000000000..d55effbd78 --- /dev/null +++ b/src/tm_mad/vmware/functions.sh @@ -0,0 +1,61 @@ +# ---------------------------------------------------------------------------- # +# Copyright 2010-2011, C12G Labs S.L # +# # +# 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. # +# ---------------------------------------------------------------------------- # + +#Symlinks the dst_path to dst_path.iso if it is an ISO file +function fix_iso { + dst_path=$1 + + if [ -f $dst_path ]; then + file -b $dst_path | grep "ISO 9660" > /dev/null 2>&1 + + if [ $? -eq 0 ]; then + bname=`basename $dst_path` + exec_and_log "ln -s $bname $dst_path/$bname.iso" \ + "Can not link ISO file." + fi + fi +} + +#Creates the VM dir +function create_vmdir { + dst_path=$1 + + log "Creating directory `basename $dst_path`" + exec_and_log "mkdir -p $dst_path" + exec_and_log "chmod a+rw $dst_path" +} + +#Makes path src ($1) relative to dst ($2) +function make_relative { + src=$1 + dst=$2 + + common=$dst + + while [ -z "`echo $src | grep -E "^$common"`" ]; do + common=`dirname $common` + dots="../$dots" + done + + echo $dots${src#$common/} +} + +#Test if the source file is a disk (and not the image dir for the VM) +function is_disk { + echo $1 | grep -q 'disk\.[0-9]\+$' > /dev/null 2>&1 + echo $? +} + diff --git a/src/tm_mad/vmware/tm_clone.sh b/src/tm_mad/vmware/tm_clone.sh index 09a337fb03..aacc251c71 100755 --- a/src/tm_mad/vmware/tm_clone.sh +++ b/src/tm_mad/vmware/tm_clone.sh @@ -26,6 +26,7 @@ else fi . $TMCOMMON +. "`dirname $0`/functions.sh" get_vmdir @@ -37,34 +38,11 @@ fix_paths log_debug "$1 $2" log_debug "DST: $DST_PATH" -DST_DIR=`dirname $DST_PATH` +create_vmdir $DST_PATH -log "Creating directory $DST_DIR" -exec_and_log "rm -rf $DST_DIR" -exec_and_log "mkdir -p $DST_PATH" -exec_and_log "chmod a+w $DST_PATH" +log "Cloning $SRC_PATH" -case $SRC in -http://*) - log "Downloading $SRC" - exec_and_log "$WGET -O $DST_PATH $SRC" \ - "Error downloading $SRC" - ;; - -*) - log "Cloning $SRC_PATH" - exec_and_log "cp -r $SRC_PATH/* $DST_PATH" \ - "Error copying $SRC to $DST" - ;; -esac - -SRC_FILE_SUFFIX=`echo ${SRC_PATH##*.}` - -if [ "x$SRC_FILE_SUFFIX" == "xiso" ]; then - cd $DST_DIR - DISK_NAME = `basename $DST_PATH` - ln -s $DISK_NAME $DISK_NAME.iso -fi - -exec_and_log "chmod a+rw $DST_PATH" +exec_and_log "cp -r $SRC_PATH/* $DST_PATH" \ + "Error copying $SRC to $DST" +fix_iso $DST_PATH diff --git a/src/tm_mad/vmware/tm_context.sh b/src/tm_mad/vmware/tm_context.sh new file mode 100755 index 0000000000..3b26f50627 --- /dev/null +++ b/src/tm_mad/vmware/tm_context.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +# ---------------------------------------------------------------------------- # +# Copyright 2010-2011, C12G Labs S.L # +# # +# 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. # +# ---------------------------------------------------------------------------- # + +while (( "$#" )); do + if [ "$#" == "1" ]; then + DST=$1 + else + SRC="$SRC $1" + fi + shift +done + + +if [ -z "${ONE_LOCATION}" ]; then + TMCOMMON=/usr/lib/one/mads/tm_common.sh +else + TMCOMMON=$ONE_LOCATION/lib/mads/tm_common.sh +fi + +. $TMCOMMON +. "`dirname $0`/functions.sh" + +get_vmdir + +DST_PATH=`arg_path $DST` + +fix_dst_path + +DST_DIR=`dirname $DST_PATH` +ISO_DIR=$DST_DIR/isofiles + +exec_and_log "mkdir -p $ISO_DIR" + +for f in $SRC; do + case $f in + http://*) + exec_and_log "$WGET -O $ISO_DIR $f" + ;; + + *) + exec_and_log "cp -R $f $ISO_DIR" + ;; + esac +done + +exec_and_log "$MKISOFS -o $DST_PATH.iso -J -R $ISO_DIR" + +exec_and_log "rm -rf $ISO_DIR" diff --git a/src/tm_mad/vmware/tm_ln.sh b/src/tm_mad/vmware/tm_ln.sh index d815341511..805e7de61c 100755 --- a/src/tm_mad/vmware/tm_ln.sh +++ b/src/tm_mad/vmware/tm_ln.sh @@ -26,6 +26,7 @@ else fi . $TMCOMMON +. "`dirname $0`/functions.sh" get_vmdir @@ -34,30 +35,21 @@ DST_PATH=`arg_path $DST` fix_dst_path -DST_DIR=`dirname $DST_PATH` +create_vmdir $DST_PATH -# SRC_PATH needs to be made relative to $ONE_LOCATION/var -VM_FOLDER_NAME=`basename $SRC_PATH` -REPO_NAME="images" -RELATIVE_SRC_PATH="../../$REPO_NAME/$VM_FOLDER_NAME" - -log "Creating directory $DST_PATH" -exec_and_log "rm -rf $DST" -exec_and_log "mkdir -p $DST_PATH" -exec_and_log "chmod a+w $DST_PATH" +# ---------------------------------------------------------------------------- # +# Link all files of the disk directory. Note that link paths needs to be # +# relative in order to be accessible from the vSphere Data Store # +# ---------------------------------------------------------------------------- # +REL_SRC_PATH=`make_relative $SRC_PATH $DST_PATH` log "Link all files in $SRC_PATH to $DST_PATH" -IMAGE_DIR=`dirname $DST_PATH` -cd $IMAGE_DIR - -for file in `find $RELATIVE_SRC_PATH/* -type f`; do - file_name=`basename $file` - exec_and_log "ln -sf ../$file $DST_PATH/$file_name" +for file in `find $SRC_PATH -type f`; do + FNAME=`basename $file` + exec_and_log "ln -sf $REL_SRC_PATH/$FNAME $DST_PATH/$FNAME" done -# Put the symlink mark for tm_mv -exec_and_log "ln -sf $RELATIVE_SRC_PATH $DST_PATH/.disk" - - +#Mark this disk persistent with a symlink for tm_mv and repo mv +exec_and_log "ln -sf ${REL_SRC_PATH#../../} $DST_PATH/.disk" diff --git a/src/tm_mad/vmware/tm_mv.sh b/src/tm_mad/vmware/tm_mv.sh index 8a4b27f875..a03071bf0e 100755 --- a/src/tm_mad/vmware/tm_mv.sh +++ b/src/tm_mad/vmware/tm_mv.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash # ---------------------------------------------------------------------------- # # Copyright 2010-2011, C12G Labs S.L # @@ -28,6 +28,7 @@ else fi . $TMCOMMON +. "`dirname $0`/functions.sh" get_vmdir @@ -41,13 +42,13 @@ SRC_PATH=`fix_dir_slashes "$SRC_PATH"` if [ "$SRC_PATH" = "$DST_PATH" ]; then log "Will not move, source and destination are equal" -elif [ -f "$SRC_PATH/.disk" ]; then # This link was set in tm_ln.sh - exec_and_log "mv $SRC_PATH/.disk $DST_PATH" -elif echo $SRC_PATH | grep -q 'disk\.[0-9]\+$'; then - log "Moving $SRC_PATH" - exec_and_log "mv $SRC_PATH $DST_PATH" +elif [ -L "$SRC_PATH/.disk" ]; then + exec_and_log "mv $SRC_PATH/.disk $DST_PATH" +elif [ "`is_disk $SRC_PATH`" = "0" ] ; then + log "Moving $SRC_PATH" + exec_and_log "mv $SRC_PATH $DST_PATH" elif [ -d $SRC_PATH ]; then - log "Will not move, is not saving image" + log "Will not move, it is not saving a VM disk image" else log "Moving $SRC_PATH" exec_and_log "mv $SRC_PATH $DST_PATH" diff --git a/src/tm_mad/vmware/tm_vmware.conf b/src/tm_mad/vmware/tm_vmware.conf index c7fc099ed3..0de9eeb95e 100644 --- a/src/tm_mad/vmware/tm_vmware.conf +++ b/src/tm_mad/vmware/tm_vmware.conf @@ -20,3 +20,4 @@ MKSWAP = dummy/tm_dummy.sh MKIMAGE = dummy/tm_dummy.sh DELETE = shared/tm_delete.sh MV = vmware/tm_mv.sh +CONTEXT = vmware/tm_context.sh diff --git a/src/vmm_mad/remotes/vmware/cancel b/src/vmm_mad/remotes/vmware/cancel index aa01113c91..7352a66720 100755 --- a/src/vmm_mad/remotes/vmware/cancel +++ b/src/vmm_mad/remotes/vmware/cancel @@ -19,36 +19,19 @@ ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION) if !ONE_LOCATION - ETC_LOCATION="/etc/one" if !defined?(ETC_LOCATION) + RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION) else - ETC_LOCATION=ONE_LOCATION+"/etc" if !defined?(ETC_LOCATION) + RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION) end +$: << RUBY_LIB_LOCATION +$: << File.dirname(__FILE__) + +require 'vmware_driver' + deploy_id = ARGV[0] -@host = ARGV[1] +host = ARGV[1] -if !@host or !deploy_id - exit -1 -end - -load ETC_LOCATION + "/vmwarerc" - -if USERNAME.class!=String || PASSWORD.class!=String - warn "Bad ESX credentials, aborting" - exit -1 -end - -# Destroy the VM -data = perform_action("virsh -c #{LIBVIRT_URI} destroy #{deploy_id}") - -if data.class == Fixnum - exit data -end - -# Undefine the VM -data = perform_action("virsh -c #{LIBVIRT_URI} undefine #{deploy_id}") - -if data.class == Fixnum - exit data -end +vmware_drv = VMwareDriver.new(host) +vmware_drv.cancel(deploy_id) diff --git a/src/vmm_mad/remotes/vmware/deploy b/src/vmm_mad/remotes/vmware/deploy index 24b3623ba6..05e89cc98e 100755 --- a/src/vmm_mad/remotes/vmware/deploy +++ b/src/vmm_mad/remotes/vmware/deploy @@ -19,74 +19,22 @@ ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION) if !ONE_LOCATION - ETC_LOCATION="/etc/one" if !defined?(ETC_LOCATION) + RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION) else - ETC_LOCATION=ONE_LOCATION+"/etc" if !defined?(ETC_LOCATION) + RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION) end -deployment_file = ARGV[0] -@host = ARGV[1] +$: << RUBY_LIB_LOCATION +$: << File.dirname(__FILE__) -if !@host or !deployment_file - exit -1 -end +require 'vmware_driver' -load ETC_LOCATION + "/vmwarerc" +dfile = ARGV[0] +host = ARGV[1] +id = ARGV[2] -if USERNAME.class!=String || PASSWORD.class!=String - warn "Bad ESX credentials, aborting" - exit -1 -end +vmware_drv = VMwareDriver.new(host) -# Define the VM -data = perform_action("virsh -c #{LIBVIRT_URI} define #{deployment_file}") +puts vmware_drv.deploy(dfile, id) -if data.class == Fixnum - exit data -end - -domainname = "" -success = false - -data.split('\n').each{ |line| - domainname = line.match("Domain (.*) defined from (.*)") - if domainname - success = true - break - end -} - -if !success - exit -1 -end - -domainname = domainname[1] - -# Start the VM -data = perform_action("virsh -c #{LIBVIRT_URI} start #{domainname}") - -if data.class == Fixnum - exit data -end - -definedname = domainname -domainname = "" -success = false - -data.split('\n').each{ |line| - domainname = line.match("Domain (.*) started") - if domainname - success = true - break - end -} - -if !success - exit -1 -end - -if definedname != domainname[1] - exit -1 -else - puts definedname -end +exit 0 diff --git a/src/vmm_mad/remotes/vmware/poll b/src/vmm_mad/remotes/vmware/poll index c304b45f3b..f4fa915cb2 100755 --- a/src/vmm_mad/remotes/vmware/poll +++ b/src/vmm_mad/remotes/vmware/poll @@ -16,62 +16,23 @@ # limitations under the License. # # ---------------------------------------------------------------------------- # + ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION) if !ONE_LOCATION - ETC_LOCATION="/etc/one" if !defined?(ETC_LOCATION) + RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION) else - ETC_LOCATION=ONE_LOCATION+"/etc" if !defined?(ETC_LOCATION) + RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION) end +$: << RUBY_LIB_LOCATION +$: << File.dirname(__FILE__) + +require 'vmware_driver' deploy_id = ARGV[0] -@host = ARGV[1] - -if !@host or !deploy_id - exit -1 -end - -load ETC_LOCATION + "/vmwarerc" - -if USERNAME.class!=String || PASSWORD.class!=String - warn "Bad ESX credentials, aborting" - exit -1 -end - -data = perform_action( - "virsh -c #{LIBVIRT_URI} --readonly dominfo #{deploy_id}") - - if data.class == Fixnum - puts "STATE=d" - exit 0 - end - -state = "" - -data.split('\n').each{ |line| - state = line.match("^State: (.*)") - - if state - state = state[1].strip - break - end -} - -state_short = "" - -case state - when "running","blocked","shutdown","dying" - state_short = 'a' - when "paused" - state_short = 'p' - when "crashed" - state_short = 'c' - else - state_short = 'd' -end - -puts "STATE=#{state_short}" - +host = ARGV[1] +vmware_drv = VMwareDriver.new(host) +puts vmware_drv.poll(deploy_id) diff --git a/src/vmm_mad/remotes/vmware/reboot b/src/vmm_mad/remotes/vmware/reboot new file mode 100755 index 0000000000..3c61f64e3b --- /dev/null +++ b/src/vmm_mad/remotes/vmware/reboot @@ -0,0 +1,37 @@ +#!/usr/bin/env ruby + +# ---------------------------------------------------------------------------- # +# Copyright 2010-2011, C12G Labs S.L # +# # +# 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. # +# ---------------------------------------------------------------------------- # + +ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION) + +if !ONE_LOCATION + RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION) +else + RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION) +end + +$: << RUBY_LIB_LOCATION +$: << File.dirname(__FILE__) + +require 'vmware_driver' + +deploy_id = ARGV[0] +host = ARGV[1] + +vmware_drv = VMwareDriver.new(host) + +vmware_drv.reboot(deploy_id) diff --git a/src/vmm_mad/remotes/vmware/restore b/src/vmm_mad/remotes/vmware/restore index f50ac54d36..feced12ea8 100755 --- a/src/vmm_mad/remotes/vmware/restore +++ b/src/vmm_mad/remotes/vmware/restore @@ -19,71 +19,19 @@ ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION) if !ONE_LOCATION - ETC_LOCATION="/etc/one" if !defined?(ETC_LOCATION) + RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION) else - ETC_LOCATION=ONE_LOCATION+"/etc" if !defined?(ETC_LOCATION) + RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION) end -file = ARGV[0] -@host = ARGV[1] - -if !@host or !file - exit -1 -end - -load ETC_LOCATION + "/vmwarerc" - -if USERNAME.class!=String || PASSWORD.class!=String - warn "Bad ESX credentials, aborting" - exit -1 -end - -# Define the VM -deployment_file = File.dirname(File.dirname(file)) + "/deployment.0" - -data = perform_action("virsh -c #{LIBVIRT_URI} define #{deployment_file}") - -if data.class == Fixnum - exit data -end - -domainname = "" -success = false - -data.split('\n').each{ |line| - domainname = line.match("Domain (.*) defined from (.*)") - if domainname - success = true - break - end -} - -if !success - exit -1 -end - -domainname = domainname[1] - -# Revert snapshot VM -# Note: This assumes the checkpoint name is "checkpoint", to change this -# it is needed to change also -# $ONE_LOCATION/lib/remotes/vmm/vmware/checkpoint - -data = perform_action( - "virsh -c #{LIBVIRT_URI} snapshot-revert #{domainname} checkpoint") - -if data.class == Fixnum - exit data -end - -# Delete checkpoint -data = perform_action( - "virsh -c #{LIBVIRT_URI} snapshot-delete #{domainname} checkpoint") - -if data.class == Fixnum - exit data -end +$: << RUBY_LIB_LOCATION +$: << File.dirname(__FILE__) +require 'vmware_driver' +checkpoint_file = ARGV[0] +host = ARGV[1] +vmware_drv = VMwareDriver.new(host) +vmware_drv.restore(checkpoint_file) diff --git a/src/vmm_mad/remotes/vmware/save b/src/vmm_mad/remotes/vmware/save index d88d1923ce..60f7eb87eb 100755 --- a/src/vmm_mad/remotes/vmware/save +++ b/src/vmm_mad/remotes/vmware/save @@ -19,50 +19,20 @@ ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION) if !ONE_LOCATION - ETC_LOCATION = "/etc/one" if !defined?(ETC_LOCATION) - VAR_LOCATION = "/var/lib/one" if !defined?(VAR_LOCATION) + RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION) else - ETC_LOCATION = ONE_LOCATION + "/etc" if !defined?(ETC_LOCATION) - VAR_LOCATION = ONE_LOCATION + "/var" if !defined?(VAR_LOCATION) + RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION) end -deploy_id = ARGV[0] -file = ARGV[1] -@host = ARGV[2] +$: << RUBY_LIB_LOCATION +$: << File.dirname(__FILE__) -if !@host or !deploy_id or !file - exit -1 -end +require 'vmware_driver' -load ETC_LOCATION + "/vmwarerc" - -if USERNAME.class!=String || PASSWORD.class!=String - warn "Bad ESX credentials, aborting" - exit -1 -end - -# Create snapshot -checkpoint_xml_file = VAR_LOCATION + "/remotes/vmm/vmware/checkpoint" - -data = perform_action( - "virsh -c #{LIBVIRT_URI} snapshot-create #{deploy_id} #{checkpoint_xml_file}") - -if data.class == Fixnum - exit data -end - -# Suspend VM -data = perform_action("virsh -c #{LIBVIRT_URI} suspend #{deploy_id}") - -if data.class == Fixnum - exit data -end - -# Undefine VM -data = perform_action("virsh -c #{LIBVIRT_URI} undefine #{deploy_id}") - -if data.class == Fixnum - exit data -end +deploy_id = ARGV[0] +file = ARGV[1] +host = ARGV[2] +vmware_drv = VMwareDriver.new(host) +vmware_drv.save(deploy_id) diff --git a/src/vmm_mad/remotes/vmware/shutdown b/src/vmm_mad/remotes/vmware/shutdown index 04bcb64238..b154da7dd9 100755 --- a/src/vmm_mad/remotes/vmware/shutdown +++ b/src/vmm_mad/remotes/vmware/shutdown @@ -19,44 +19,19 @@ ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION) if !ONE_LOCATION - ETC_LOCATION="/etc/one" if !defined?(ETC_LOCATION) + RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION) else - ETC_LOCATION=ONE_LOCATION+"/etc" if !defined?(ETC_LOCATION) + RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION) end +$: << RUBY_LIB_LOCATION +$: << File.dirname(__FILE__) + +require 'vmware_driver' + deploy_id = ARGV[0] -@host = ARGV[1] - -if !@host or !deploy_id - exit -1 -end - -load ETC_LOCATION + "/vmwarerc" - -if USERNAME.class!=String || PASSWORD.class!=String - warn "Bad ESX credentials, aborting" - exit -1 -end - -data = perform_action("virsh -c #{LIBVIRT_URI} shutdown #{deploy_id}") - -if data.class == Fixnum - exit data -end - -begin - data = perform_action("virsh -c #{LIBVIRT_URI} list") - if data.class == Fixnum - exit data - end - sleep 2 -end while data.match(deploy_id) - -data = perform_action("virsh -c #{LIBVIRT_URI} undefine #{deploy_id}") - -if data.class == Fixnum - exit data -end - +host = ARGV[1] +vmware_drv = VMwareDriver.new(host) +vmware_drv.shutdown(deploy_id) diff --git a/src/vmm_mad/remotes/vmware/vmware_driver.rb b/src/vmm_mad/remotes/vmware/vmware_driver.rb new file mode 100644 index 0000000000..6841906fe2 --- /dev/null +++ b/src/vmm_mad/remotes/vmware/vmware_driver.rb @@ -0,0 +1,297 @@ +# ---------------------------------------------------------------------------- # +# Copyright 2010-2011, C12G Labs S.L # +# # +# 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. # +# ---------------------------------------------------------------------------- # + +require "scripts_common" +require 'yaml' +require "CommandManager" + +class VMwareDriver + # -------------------------------------------------------------------------# + # Set up the environment for the driver # + # -------------------------------------------------------------------------# + ONE_LOCATION = ENV["ONE_LOCATION"] + + if !ONE_LOCATION + BIN_LOCATION = "/usr/bin" + LIB_LOCATION = "/usr/lib/one" + ETC_LOCATION = "/etc/one/" + VAR_LOCATION = "/var/lib/one" + else + LIB_LOCATION = ONE_LOCATION + "/lib" + BIN_LOCATION = ONE_LOCATION + "/bin" + ETC_LOCATION = ONE_LOCATION + "/etc/" + VAR_LOCATION = ONE_LOCATION + "/var/" + end + + CONF_FILE = ETC_LOCATION + "/vmwarerc" + CHECKPOINT = VAR_LOCATION + "/remotes/vmm/vmware/checkpoint" + + ENV['LANG'] = 'C' + + SHUTDOWN_INTERVAL = 5 + SHUTDOWN_TIMEOUT = 500 + + def initialize(host) + conf = YAML::load(File.read(CONF_FILE)) + + @uri = conf[:libvirt_uri].gsub!('@HOST@', host) + + @user = conf[:username] + @pass = conf[:password] + end + + # ######################################################################## # + # VMWARE DRIVER ACTIONS # + # ######################################################################## # + + # ------------------------------------------------------------------------ # + # Deploy & define a VM based on its description file # + # ------------------------------------------------------------------------ # + def deploy(dfile, id) + # Define the domain if it is not already defined (e.g. from UNKNOWN) + + if not domain_defined?(id) + deploy_id = define_domain(dfile) + + exit -1 if deploy_id.nil? + else + deploy_id = "one-#{id}" + end + + OpenNebula.log_debug("Successfully defined domain #{deploy_id}.") + + # Start the VM + rc, info = do_action("virsh -c #{@uri} start #{deploy_id}") + + if rc == false + undefine_domain(deploy_id) + exit info + end + + return deploy_id + end + + # ------------------------------------------------------------------------ # + # Cancels & undefine the VM # + # ------------------------------------------------------------------------ # + def cancel(deploy_id) + # Destroy the VM + rc, info = do_action("virsh -c #{@uri} destroy #{deploy_id}") + + exit info if rc == false + + OpenNebula.log_debug("Successfully canceled domain #{deploy_id}.") + + # Undefine the VM + undefine_domain(deploy_id) + end + + # ------------------------------------------------------------------------ # + # Reboots a running VM # + # ------------------------------------------------------------------------ # + def reboot(deploy_id) + rc, info = do_action("virsh -c #{@uri} reboot #{deploy_id}") + + exit info if rc == false + + OpenNebula.log_debug("Domain #{deploy_id} successfully rebooted.") + end + # ------------------------------------------------------------------------ # + # Migrate # + # ------------------------------------------------------------------------ # + def migrate + OpenNebula.log_error("Migration action is currently not supported") + exit -1 + end + + # ------------------------------------------------------------------------ # + # Monitor a VM # + # ------------------------------------------------------------------------ # + def poll(deploy_id) + rc, info = do_action("virsh -c #{@uri} --readonly dominfo #{deploy_id}") + + return "STATE=d" if rc == false + + state = "" + + info.split('\n').each{ |line| + mdata = line.match("^State: (.*)") + + if mdata + state = mdata[1].strip + break + end + } + + case state + when "running","blocked","shutdown","dying" + state_short = 'a' + when "paused" + state_short = 'p' + when "crashed" + state_short = 'c' + else + state_short = 'd' + end + + return "STATE=#{state_short}" + end + + # ------------------------------------------------------------------------ # + # Restore a VM from a previously saved checkpoint # + # ------------------------------------------------------------------------ # + def restore(checkpoint) + begin + # Define the VM + dfile = File.dirname(File.dirname(checkpoint)) + "/deployment.0" + rescue => e + OpenNebula.log_error("Can not open checkpoint #{e.message}") + exit -1 + end + + deploy_id = define_domain(dfile) + + exit -1 if deploy_id.nil? + + # Revert snapshot VM + # Note: This assumes the checkpoint name is "checkpoint", to change + # this it is needed to change also [1] + # + # [1] $ONE_LOCATION/lib/remotes/vmm/vmware/checkpoint + + rc, info = do_action( + "virsh -c #{@uri} snapshot-revert #{deploy_id} checkpoint") + + exit info if rc == false + + # Delete checkpoint + rc, info = do_action( + "virsh -c #{@uri} snapshot-delete #{deploy_id} checkpoint") + + OpenNebula.log_error("Could not delete snapshot") if rc == false + end + + # ------------------------------------------------------------------------ # + # Saves a VM taking a snapshot # + # ------------------------------------------------------------------------ # + def save(deploy_id) + # Take a snapshot for the VM + rc, info = do_action( + "virsh -c #{@uri} snapshot-create #{deploy_id} #{CHECKPOINT}") + + exit info if rc == false + + # Suspend VM + rc, info = do_action("virsh -c #{@uri} suspend #{deploy_id}") + + exit info if rc == false + + # Undefine VM + undefine_domain(deploy_id) + end + + # ------------------------------------------------------------------------ # + # Shutdown a VM # + # ------------------------------------------------------------------------ # + def shutdown(deploy_id) + rc, info = do_action("virsh -c #{@uri} shutdown #{deploy_id}") + + exit info if rc == false + + counter = 0 + + begin + rc, info = do_action("virsh -c #{@uri} list") + info = "" if rc == false + + sleep SHUTDOWN_INTERVAL + + counter = counter + SHUTDOWN_INTERVAL + end while info.match(deploy_id) and counter < SHUTDOWN_TIMEOUT + + if counter >= SHUTDOWN_TIMEOUT + OpenNebula.error_message( + "Timeout reached, VM #{deploy_id} is still alive") + exit - 1 + end + + undefine_domain(deploy_id) + end + + # ######################################################################## # + # DRIVER HELPER FUNCTIONS # + # ######################################################################## # + + private + + #Generates an ESX command using ttyexpect + def esx_cmd(command) + cmd = "#{BIN_LOCATION}/tty_expect -u #{@user} -p #{@pass} #{command}" + end + + #Performs a action usgin libvirt + def do_action(cmd) + rc = LocalCommand.run(esx_cmd(cmd)) + + if rc.code == 0 + return [true, rc.stdout] + else + err = "Error executing: #{cmd} err: #{rc.stderr} out: #{rc.stdout}" + OpenNebula.log_error(err) + return [false, rc.code] + end + end + + # Undefines a domain in the ESX hypervisor + def undefine_domain(id) + rc, info = do_action("virsh -c #{@uri} undefine #{id}") + + if rc == false + OpenNebula.log_error("Error undefining domain #{id}") + OpenNebula.log_error("Domain #{id} has to be undefined manually") + return info + end + + return 0 + end + + #defines a domain in the ESX hypervisor + def define_domain(dfile) + deploy_id = nil + rc, info = do_action("virsh -c #{@uri} define #{dfile}") + + return nil if rc == false + + info.split('\n').each{ |line| + mdata = line.match("Domain (.*) defined from (.*)") + + if mdata + deploy_id = mdata[1] + break + end + } + + deploy_id.strip! + + return deploy_id + end + + def domain_defined?(one_id) + rc, info = do_action("virsh -c #{@uri} dominfo one-#{one_id}") + + return rc + end +end diff --git a/src/vmm_mad/remotes/vmware/vmwarerc b/src/vmm_mad/remotes/vmware/vmwarerc index e3267f3ea6..4f789d2f31 100644 --- a/src/vmm_mad/remotes/vmware/vmwarerc +++ b/src/vmm_mad/remotes/vmware/vmwarerc @@ -14,28 +14,11 @@ # limitations under the License. # # ---------------------------------------------------------------------------- # -# User configurable variables (Ruby syntax) -LIBVIRT_URI = "esx://@HOST@/?no_verify=1" -QEMU_PROTOCOL = "qemu" +# Libvirt configuration + +:libvirt_uri: "esx://@HOST@/?no_verify=1" +:qemu_protocol: "qemu" # Username and password of the VMware hypervisor -USERNAME = "oneadmin" -PASSWORD = - -# Loading the vmware library for mads -# Please leave this uncommented -ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION) - -if !ONE_LOCATION - LIB_LOCATION = "/usr/lib/one" if !defined?(LIB_LOCATION) -else - LIB_LOCATION = ONE_LOCATION+"/lib" if !defined?(LIB_LOCATION) -end - -load LIB_LOCATION + "/ruby/vmwarelib.rb" - -ENV['LANG']='C' - - - - +:username: "oneadmin" +:password: \ No newline at end of file