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

Merge remote-tracking branch 'origin/feature-1664-clusters' into feature-1664

This commit is contained in:
Daniel Molina 2013-01-24 17:40:46 +01:00
commit 42beabf893
64 changed files with 2967 additions and 803 deletions

View File

@ -102,6 +102,13 @@ public:
Template::get(_name,value);
};
void get(const char *name, bool& value) const
{
string _name(name);
Template::get(_name,value);
};
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------

View File

@ -140,6 +140,11 @@ public:
return name;
};
void set_name(const string& _name)
{
name = _name;
};
int get_uid() const
{
return uid;

View File

@ -182,6 +182,15 @@ protected:
*/
void cleanup_quota(const string& qid);
/**
* Creates a string from the given float, using fixed notation. If the
* number has any decimals, they will be truncated to 2.
*
* @param num
* @return
*/
string float_to_str(const float &num);
private:
/**
* Creates an empty quota based on the given attribute. The attribute va

View File

@ -109,7 +109,7 @@ public:
VirtualMachineAllocate():
RequestManagerAllocate("VirtualMachineAllocate",
"Allocates a new virtual machine",
"A:ss",
"A:ssb",
true)
{
Nebula& nd = Nebula::instance();

View File

@ -0,0 +1,166 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.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. */
/* -------------------------------------------------------------------------- */
#ifndef REQUEST_MANAGER_RENAME_H_
#define REQUEST_MANAGER_RENAME_H_
#include "Request.h"
#include "Nebula.h"
using namespace std;
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class RequestManagerRename : public Request
{
protected:
RequestManagerRename(const string& method_name,
const string& help,
const string& params = "A:sis")
:Request(method_name,params,help)
{
auth_op = AuthRequest::MANAGE;
};
virtual ~RequestManagerRename(){};
/* -------------------------------------------------------------------- */
void request_execute(xmlrpc_c::paramList const& _paramList,
RequestAttributes& att);
virtual PoolObjectSQL * get(const string& name, int uid, bool lock) = 0;
};
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class VirtualMachineRename : public RequestManagerRename
{
public:
VirtualMachineRename():
RequestManagerRename("VirtualMachineRename","Renames a virtual machine")
{
Nebula& nd = Nebula::instance();
pool = nd.get_vmpool();
auth_object = PoolObjectSQL::VM;
};
~VirtualMachineRename(){};
PoolObjectSQL * get(const string& name, int uid, bool lock)
{
return 0;
};
};
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class TemplateRename : public RequestManagerRename
{
public:
TemplateRename():
RequestManagerRename("TemplateRename",
"Renames a virtual machine template")
{
Nebula& nd = Nebula::instance();
pool = nd.get_tpool();
auth_object = PoolObjectSQL::TEMPLATE;
};
~TemplateRename(){};
PoolObjectSQL * get(const string& name, int uid, bool lock)
{
return static_cast<VMTemplatePool*>(pool)->get(name, uid, lock);
};
};
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class VirtualNetworkRename: public RequestManagerRename
{
public:
VirtualNetworkRename():
RequestManagerRename("VirtualNetworkRename","Renames a virtual network")
{
Nebula& nd = Nebula::instance();
pool = nd.get_vnpool();
auth_object = PoolObjectSQL::NET;
};
~VirtualNetworkRename(){};
PoolObjectSQL * get(const string& name, int uid, bool lock)
{
return static_cast<VirtualNetworkPool*>(pool)->get(name, uid, lock);
};
};
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class ImageRename: public RequestManagerRename
{
public:
ImageRename():
RequestManagerRename("ImageRename", "Renames an image")
{
Nebula& nd = Nebula::instance();
pool = nd.get_ipool();
auth_object = PoolObjectSQL::IMAGE;
};
~ImageRename(){};
PoolObjectSQL * get(const string& name, int uid, bool lock)
{
return static_cast<ImagePool*>(pool)->get(name, uid, lock);
};
};
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class DocumentRename : public RequestManagerRename
{
public:
DocumentRename():
RequestManagerRename("DocumentRename", "Renames a generic document")
{
Nebula& nd = Nebula::instance();
pool = nd.get_docpool();
auth_object = PoolObjectSQL::DOCUMENT;
};
~DocumentRename(){};
PoolObjectSQL * get(const string& name, int uid, bool lock)
{
return 0;
};
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#endif

View File

@ -57,7 +57,7 @@ public:
VMTemplateInstantiate():
RequestManagerVMTemplate("TemplateInstantiate",
"Instantiates a new virtual machine using a template",
"A:sis")
"A:sisb")
{
auth_op = AuthRequest::USE;
};

View File

@ -62,10 +62,16 @@ protected:
string& vnm,
string& tm,
string& ds_location,
int& ds_id,
int& ds_id,
RequestAttributes& att,
PoolObjectAuth& host_perms);
bool check_host(int hid,
int cpu,
int mem,
int disk,
string& error);
int add_history(VirtualMachine * vm,
int hid,
const string& hostname,
@ -106,7 +112,7 @@ public:
VirtualMachineDeploy():
RequestManagerVirtualMachine("VirtualMachineDeploy",
"Deploys a virtual machine",
"A:sii")
"A:siib")
{
auth_op = AuthRequest::ADMIN;
};
@ -126,7 +132,7 @@ public:
VirtualMachineMigrate():
RequestManagerVirtualMachine("VirtualMachineMigrate",
"Migrates a virtual machine",
"A:siib")
"A:siibb")
{
auth_op = AuthRequest::ADMIN;
};

View File

@ -265,6 +265,19 @@ public:
const string& name,
float& value) const;
/**
* Gets the value of a Single attributes (bool) with the given name.
* @param name the attribute name.
* @param value the attribute value, a bool, false if the attribute is not
* defined or not Single
*
* @return True if the Single attribute was found and is a valid bool
* value
*/
virtual bool get(
const string& name,
bool& value) const;
friend ostream& operator<<(ostream& os, const Template& t);
/**

View File

@ -37,7 +37,8 @@ public:
const string& hook_location,
const string& remotes_location,
vector<const Attribute *>& restricted_attrs,
time_t expire_time);
time_t expire_time,
bool on_hold);
~VirtualMachinePool(){};
@ -255,6 +256,11 @@ private:
* Size, in seconds, of the historical monitoring information
*/
static time_t _monitor_expiration;
/**
* True or false whether to submit new VM on HOLD or not
*/
static bool _submit_on_hold;
};
#endif /*VIRTUAL_MACHINE_POOL_H_*/

View File

@ -183,7 +183,8 @@ else
CHOWN_DIRS="$ROOT"
fi
SHARE_DIRS="$SHARE_LOCATION/examples"
SHARE_DIRS="$SHARE_LOCATION/examples \
$SHARE_LOCATION/tgt"
ETC_DIRS="$ETC_LOCATION/im_ec2 \
$ETC_LOCATION/vmm_ec2 \
@ -451,6 +452,7 @@ INSTALL_FILES=(
NETWORK_OVSWITCH_FILES:$VAR_LOCATION/remotes/vnm/ovswitch
NETWORK_VMWARE_FILES:$VAR_LOCATION/remotes/vnm/vmware
EXAMPLE_SHARE_FILES:$SHARE_LOCATION/examples
TGT_SHARE_FILES:$SHARE_LOCATION/tgt
INSTALL_NOVNC_SHARE_FILE:$SHARE_LOCATION
INSTALL_GEMS_SHARE_FILE:$SHARE_LOCATION
HOOK_FT_FILES:$VAR_LOCATION/remotes/hooks/ft
@ -1065,6 +1067,12 @@ EXAMPLE_SHARE_FILES="share/examples/vm.template \
share/examples/private.net \
share/examples/public.net"
#-------------------------------------------------------------------------------
# File required to interact with a tgtd server
#-------------------------------------------------------------------------------
TGT_SHARE_FILES="share/scripts/tgt/tgt-setup-lun-one"
#-------------------------------------------------------------------------------
# HOOK scripts, to be installed under $VAR_LOCATION/remotes/hooks
#-------------------------------------------------------------------------------

View File

@ -38,6 +38,9 @@
# VMID
#
# DEBUG_LEVEL: 0 = ERROR, 1 = WARNING, 2 = INFO, 3 = DEBUG
#
# VM_SUBMIT_ON_HOLD: Forces VMs to be created on hold state instead of pending.
# Values: YES or NO.
#*******************************************************************************
#MANAGER_TIMER = 30
@ -68,6 +71,8 @@ VNC_BASE_PORT = 5900
DEBUG_LEVEL = 3
#VM_SUBMIT_ON_HOLD = "NO"
#*******************************************************************************
# Physical Networks configuration
#*******************************************************************************

View File

@ -0,0 +1,279 @@
#!/bin/bash
# LUN assignment script
#
# Copyright (C) 2007 Erez Zilber <erezz@voltaire.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation, version 2 of the
# License.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301 USA
usage()
{
name=$(basename $0);
echo "usage:";
echo -e "\t$name -n tgt_name -d dev -b bs_name -t transport [initiator_IP1 initiator_IP2 ...]";
echo "defaults:";
echo -e "\tbacking store: rdwr";
echo -e "\ttransport: iscsi";
echo -e "\tinitiator: ALL";
echo "examples:";
echo -e "\t$name -n tgt-1 -d /dev/sdb1 192.168.1.2";
echo -e "\t$name -n tgt-2 -d /tmp/null -b null -t iser";
echo -e "\t$name -n tgt-3 -d ~/disk3.bin -b rdwr 192.168.1.2 192.168.1.3";
}
verify_params()
{
if ! [ "$dev" -o "$bs_type" == "null" ]; then
echo "Error: a device is mandatory";
exit 1;
else
return;
fi
# Make sure that the device exists
if ! [ -b $dev -o -f $dev -o -c $dev ]; then
echo "Error: $dev is not a device";
exit 1;
fi
if ! [ "$tgt_name" ]; then
echo "Error: target name is mandatory";
exit 1;
fi
if ! [ "$lld_name" ]; then
echo "Error: lld name empty";
exit 1;
fi
}
find_vacant_tgt_id()
{
tmp_file=`mktemp`
tgtadm --lld $lld_name --op show --mode target | strings > $tmp_file
id_list=$(cat $tmp_file | grep Target | cut -d" " -f2 | sed s/://)
next_vacant_id=1
for id in $id_list; do
if (($id > $next_vacant_id)); then
break;
else
next_vacant_id=$((next_vacant_id+1))
fi
done
rm -f $tmp_file
echo $next_vacant_id
}
find_vacant_lun()
{
tid=$1
tgt_found=0
next_vacant_lun=0
tmp_file=`mktemp`
tgtadm --lld $lld_name --op show --mode target | strings | tgt-admin -s | grep 'LUN\|Target' > $tmp_file
retcode=$?
while read line; do
# Check if we finished going over this target
if ((tgt_found == 1 && $(echo $line | grep -c "^Target") == 1)); then
break
fi
# Check if we found the requested target
if (($(echo $line | grep -c "Target $tid:") == 1)); then
tgt_found=1
continue
fi
if ((tgt_found == 1 && $(echo $line | grep -c "LUN:") == 1)); then
curr_lun=$(echo $line | cut -d" " -f2)
if (($curr_lun > $next_vacant_lun)); then
break
else
next_vacant_lun=$((next_vacant_lun+1))
fi
fi
done < $tmp_file
rm -f $tmp_file
if ((tgt_found == 0)); then
echo "Error: could not find a LUN for target $tid, guessing 1 as next vacant LUN"
return 1
fi
if ((next_vacant_lun == 0)); then
echo "Error: could not find a LUN for target $tid, guessing 1 as next vacant LUN"
return 1
fi
return $next_vacant_lun
}
err_exit()
{
if ((new_tgt == 0)); then
exit 1
fi
echo "Deleting new target, tid=$tid"
tgtadm --lld $lld_name --op delete --mode target --tid $tid
res=$?
if [ $res -ne 0 ]; then
echo "Error: failed to delete target, tid=$tid"
fi
exit 1
}
check_if_tgt_exists()
{
tgt_list=$(tgtadm --lld $lld_name --op show --mode target | strings | grep Target | cut -d" " -f3)
for curr_tgt in $tgt_list; do
if [ $tgt_name = $curr_tgt ]; then
return 1
fi
done
return 0
}
if [ $# -eq 0 ]; then
usage
exit 1
fi
lld_name="iscsi"
while getopts "d:n:b:t:h:" opt
do
case ${opt} in
d)
dev=$OPTARG;;
n)
tgt_name=$OPTARG;;
b)
bs_type=$OPTARG;;
t)
lld_name=$OPTARG;;
h*)
usage
exit 1
esac
done
shift $(($OPTIND - 1))
initiators=$*
verify_params
# Check if tgtd is running (we should have 2 daemons)
tgtd_count=`pidof tgtd | wc -w`
if [ $tgtd_count -lt 1 ]; then
echo "tgtd is not running"
echo "Exiting..."
exit 1
fi
echo "Using transport: $lld_name"
if ! [[ $tgt_name =~ ^iqn ]]; then
tgt_name="iqn.2001-04.com.$(hostname -s)-$tgt_name"
fi
# Make sure that a target with the same name doesn't exist
check_if_tgt_exists
if [ $? -eq 1 ]; then
echo "Error: target named $tgt_name already exists"
read -p "Add a new lun to the existing target? (yes/NO): " add_lun
if [ $add_lun != "yes" ]; then
exit 1
fi
tid=$(tgtadm --lld $lld_name --op show --mode target | strings | grep $tgt_name | cut -d" " -f2)
tid=${tid%:}
new_tgt=0
else
i=0
while [ true ]
do
let i=i+1
tid=`find_vacant_tgt_id`
#tid=$?
# Create the new target
echo -n "Creating new target (name=$tgt_name, tid=$tid)..."
tgtoutput=`tgtadm --lld $lld_name --op new --mode target --tid $tid -T $tgt_name 2>&1`
res=$?
if [ "$tgtoutput" == "tgtadm: this target already exists" ]; then
echo "Target already exists (this should not happen)... Attempt $i"
elif [ $res -eq 0 ]; then # output is not about duplication and return value is zero, this is the normal condition
break
fi
if [ $i -eq 100 ]; then
echo "Too many attempts, giving up"
break
fi
done
if [ $res -ne 0 ]; then
echo "Error: failed to create target (name=$tgt_name, tid=$tid)"
exit 1
fi
new_tgt=1
fi
echo "OK"
find_vacant_lun $tid
lun=$?
echo "LUN ok, $lun"
# Add a logical unit to the target
echo "Adding a logical unit ($dev) to target, tid=$tid"
if [ $bs_type ]; then
echo "Setting backing store type: $bs_type"
bs_opt="-E $bs_type"
fi
tgtadm --lld $lld_name --op new --mode logicalunit --tid $tid --lun $lun -b $dev $bs_opt
res=$?
if [ $res -ne 0 ]; then
echo "Error: failed to add a logical unit ($dev) to target, tid=$tid"
err_exit
fi
# Define which initiators can use this target
if test "$initiators" ; then
# Allow access only for specific initiators
echo "Accepting connections only from $initiators"
for initiator in $initiators; do
tgtadm --lld $lld_name --op bind --mode target --tid $tid -I $initiator
res=$?
if [ $res -ne 0 ]; then
echo "Error: could not assign initiator $initiator to the target"
fi
done
else
# Allow access for everyone
echo "Accepting connections from all initiators"
tgtadm --lld $lld_name --op bind --mode target --tid $tid -I ALL
res=$?
if [ $res -ne 0 ]; then
echo "Error: failed to set access for all initiators"
err_exit
fi
fi

View File

@ -28,6 +28,9 @@ server 1:
:host: localhost
:port: 389
# Uncomment this line for tsl conections
#:encryption: :simple_tls
# base hierarchy where to search for users and groups
:base: 'dc=domain'

View File

@ -41,6 +41,7 @@ class LdapAuth
ops[:host]=@options[:host] if @options[:host]
ops[:port]=@options[:port].to_i if @options[:port]
ops[:encryption]=@options[:encryption] if @options[:encryption]
@ldap=Net::LDAP.new(ops)
end

View File

@ -498,15 +498,9 @@ module CommandParser
else
puts "one parameter to run"
end
puts
puts "Usage:"
if @main
print " #{@usage}\n"
else
print " #{name} "
print_command(@commands[name])
end
print_command_help(name)
exit -1
else
id=0

View File

@ -51,6 +51,12 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
}
}
HOLD = {
:name => "hold",
:large => "--hold",
:description => "Creates the new VM on hold state instead of pending"
}
def self.rname
"VM"
end

View File

@ -304,6 +304,16 @@ cmd=CommandParser::CmdParser.new(ARGV) do
end
end
rename_desc = <<-EOT.unindent
Renames the Image
EOT
command :rename, rename_desc, :imageid, :name do
helper.perform_action(args[0],options,"renamed") do |o|
o.rename(args[1])
end
end
list_desc = <<-EOT.unindent
Lists Images in the pool
EOT

View File

@ -29,6 +29,7 @@ $: << RUBY_LIB_LOCATION+"/cli"
require 'command_parser'
require 'one_helper/onetemplate_helper'
require 'one_helper/onevm_helper'
cmd=CommandParser::CmdParser.new(ARGV) do
usage "`onetemplate` <command> [<args>] [<options>]"
@ -52,7 +53,8 @@ cmd=CommandParser::CmdParser.new(ARGV) do
instantiate_options = [
OneTemplateHelper::VM_NAME,
OneTemplateHelper::MULTIPLE
OneTemplateHelper::MULTIPLE,
OneVMHelper::HOLD
]
########################################################################
@ -179,7 +181,10 @@ cmd=CommandParser::CmdParser.new(ARGV) do
exit_code=helper.perform_action(args[0],options,"instantiated") do |t|
name = options[:name]
name = name.gsub("%i",i.to_s) if name
res = t.instantiate(name)
on_hold = options[:hold] != nil
res = t.instantiate(name, on_hold)
if !OpenNebula.is_error?(res)
puts "VM ID: #{res}"
@ -265,6 +270,16 @@ cmd=CommandParser::CmdParser.new(ARGV) do
Lists Templates in the pool
EOT
rename_desc = <<-EOT.unindent
Renames the Template
EOT
command :rename, rename_desc, :templateid, :name do
helper.perform_action(args[0],options,"renamed") do |o|
o.rename(args[1])
end
end
command :list, list_desc, [:filterflag, nil], :options=>list_options do
helper.list_pool(options, false, args[0])
end

View File

@ -56,6 +56,13 @@ cmd=CommandParser::CmdParser.new(ARGV) do
:description => "Device where the image will be attached"
}
ENFORCE={
:name => "enforce",
:short => "-e",
:large => "--enforce",
:description => "Enforce that the host capacity is not exceeded"
}
########################################################################
# Global Options
########################################################################
@ -118,7 +125,8 @@ cmd=CommandParser::CmdParser.new(ARGV) do
EOT
command :create, create_desc, [:file, nil], :options =>
[OneVMHelper::MULTIPLE]+OpenNebulaHelper::TEMPLATE_OPTIONS_VM do
[OneVMHelper::MULTIPLE, OneVMHelper::HOLD]+
OpenNebulaHelper::TEMPLATE_OPTIONS_VM do
number = options[:multiple] || 1
exit_code = nil
@ -153,9 +161,11 @@ cmd=CommandParser::CmdParser.new(ARGV) do
exit 0
end
on_hold = options[:hold] != nil
number.times do
exit_code = helper.create_resource(options) do |vm|
error = vm.allocate(template)
error = vm.allocate(template, on_hold)
end
break if exit_code == -1
@ -287,12 +297,16 @@ cmd=CommandParser::CmdParser.new(ARGV) do
States: PENDING
EOT
command :deploy, deploy_desc, [:range,:vmid_list], :hostid do
command :deploy, deploy_desc, [:range,:vmid_list], :hostid, :options=>[ENFORCE] do
host_id = args[1]
verbose = "deploying in host #{host_id}"
helper.perform_actions(args[0],options,verbose) do |vm|
vm.deploy(host_id)
if !options[:enforce].nil?
vm.deploy(host_id, options[:enforce])
else
vm.deploy(host_id)
end
end
end
@ -302,12 +316,16 @@ cmd=CommandParser::CmdParser.new(ARGV) do
States: RUNNING
EOT
command :livemigrate, livemigrate_desc, [:range,:vmid_list], :hostid do
command :livemigrate, livemigrate_desc, [:range,:vmid_list], :hostid, :options=>[ENFORCE] do
host_id = args[1]
verbose = "live migrating to #{host_id}"
helper.perform_actions(args[0],options,verbose) do |vm|
vm.live_migrate(host_id)
if !options[:enforce].nil?
vm.live_migrate(host_id, options[:enforce])
else
vm.live_migrate(host_id)
end
end
end
@ -317,12 +335,16 @@ cmd=CommandParser::CmdParser.new(ARGV) do
States: RUNNING
EOT
command :migrate, migrate_desc, [:range,:vmid_list], :hostid do
command :migrate, migrate_desc, [:range,:vmid_list], :hostid, :options=>[ENFORCE] do
host_id = args[1]
verbose = "migrating to #{host_id}"
helper.perform_actions(args[0],options,verbose) do |vm|
vm.migrate(host_id)
if !options[:enforce].nil?
vm.migrate(host_id, options[:enforce])
else
vm.migrate(host_id)
end
end
end
@ -515,6 +537,16 @@ cmd=CommandParser::CmdParser.new(ARGV) do
Lists VMs in the pool
EOT
rename_desc = <<-EOT.unindent
Renames the VM
EOT
command :rename, rename_desc, :vmid, :name do
helper.perform_action(args[0],options,"renamed") do |o|
o.rename(args[1])
end
end
command :list, list_desc, [:filterflag, nil],
:options=>CLIHelper::OPTIONS+OpenNebulaHelper::OPTIONS+
[OpenNebulaHelper::DESCRIBE] do

View File

@ -228,4 +228,14 @@ cmd=CommandParser::CmdParser.new(ARGV) do
vnet.update(str)
end
end
rename_desc = <<-EOT.unindent
Renames the Virtual Network
EOT
command :rename, rename_desc, :vnetid, :name do
helper.perform_action(args[0],options,"renamed") do |o|
o.rename(args[1])
end
end
end

View File

@ -64,6 +64,9 @@ BASE_IQN="${XPATH_ELEMENTS[6]:-$BASE_IQN}"
SRC="${XPATH_ELEMENTS[7]}"
SIZE="${XPATH_ELEMENTS[8]}"
# Check if 'TGTSETUPLUN' is installed
tgt_setup_lun_install "$DST_HOST" "$BASE_PATH"
set_up_datastore "$BASE_PATH" "$RESTRICTED_DIRS" "$SAFE_DIRS" "$UMASK"
LV_NAME="lv-one-${ID}"
@ -76,13 +79,9 @@ DEV_SRC="/dev/$VG_NAME/$LV_SRC"
CLONE_CMD=$(cat <<EOF
set -e
$SUDO $LVCREATE -L${SIZE}M ${VG_NAME} -n ${LV_NAME}
$SUDO $DD if=$DEV_SRC of=$DEV bs=64k
$SUDO $DD if=$DEV_SRC of=$DEV bs=2M
TID=\$($SUDO $(tgtadm_next_tid))
$SUDO $(tgtadm_target_new "\$TID" "$IQN")
$SUDO $(tgtadm_target_bind_all "\$TID")
$SUDO $(tgtadm_logicalunit_new "\$TID" "$DEV")
$SUDO $(tgt_setup_lun "$IQN" "$DEV")
$SUDO $(tgt_admin_dump_config "$TARGET_CONF")
EOF
)

View File

@ -76,6 +76,9 @@ SHA1="${XPATH_ELEMENTS[10]}"
NO_DECOMPRESS="${XPATH_ELEMENTS[11]}"
LIMIT_TRANSFER_BW="${XPATH_ELEMENTS[12]}"
# Check if 'TGTSETUPLUN' is installed
tgt_setup_lun_install "$DST_HOST" "$BASE_PATH"
set_up_datastore "$BASE_PATH" "$RESTRICTED_DIRS" "$SAFE_DIRS" "$UMASK"
LV_NAME="lv-one-${ID}"
@ -86,13 +89,7 @@ REGISTER_CMD=$(cat <<EOF
set -e
$SUDO $LVCREATE -L${SIZE}M ${VG_NAME} -n ${LV_NAME}
TID=\$($SUDO $(tgtadm_next_tid))
[ -z "\$TID" ] && TID=1
$SUDO $(tgtadm_target_new "\$TID" "$IQN")
$SUDO $(tgtadm_target_bind_all "\$TID")
$SUDO $(tgtadm_logicalunit_new "\$TID" "$DEV")
$SUDO $(tgt_setup_lun "$IQN" "$DEV")
$SUDO $(tgt_admin_dump_config "$TARGET_CONF")
EOF
)
@ -123,7 +120,7 @@ esac
ssh_exec_and_log "$DST_HOST" "$REGISTER_CMD" "Error registering $DST_HOST:$DEV"
exec_and_log "eval $DUMP | $SSH $DST_HOST $SUDO $DD of=$DEV bs=64k" \
exec_and_log "eval $DUMP | $SSH $DST_HOST $SUDO $DD of=$DEV bs=2M" \
"Error dumping $SRC to $DST_HOST:$DEV"
echo "$IQN"

View File

@ -66,6 +66,9 @@ BASE_IQN="${XPATH_ELEMENTS[6]:-$BASE_IQN}"
FSTYPE="${XPATH_ELEMENTS[7]}"
SIZE="${XPATH_ELEMENTS[8]:-0}"
# Check if 'TGTSETUPLUN' is installed
tgt_setup_lun_install "$DST_HOST" "$BASE_PATH"
set_up_datastore "$BASE_PATH" "$RESTRICTED_DIRS" "$SAFE_DIRS" "$UMASK"
LV_NAME="lv-one-${ID}"
@ -76,12 +79,7 @@ REGISTER_CMD=$(cat <<EOF
set -e
$SUDO $LVCREATE -L${SIZE}M ${VG_NAME} -n ${LV_NAME}
TID=\$($SUDO $(tgtadm_next_tid))
[ -z "\$TID" ] && TID=1
$SUDO $(tgtadm_target_new "\$TID" "$IQN")
$SUDO $(tgtadm_target_bind_all "\$TID")
$SUDO $(tgtadm_logicalunit_new "\$TID" "$DEV")
$SUDO $(tgt_setup_lun "$IQN" "$DEV")
$SUDO $(tgt_admin_dump_config "$TARGET_CONF")
if [ "$FSTYPE" != "save_as" ]; then

View File

@ -44,6 +44,7 @@ SYNC=sync
TAR=tar
TGTADM=tgtadm
TGTADMIN=tgt-admin
TGTSETUPLUN=tgt-setup-lun-one
VMKFSTOOLS=vmkfstools
WGET=wget
@ -349,12 +350,12 @@ function tgtadm_target_delete {
function tgtadm_get_tid_for_iqn {
IQN="$1"
echo "$TGTADM --lld iscsi --op show --mode target | \
echo "$TGTADM --lld iscsi --op show --mode target | strings | \
grep \"$IQN\" | awk '{split(\$2,tmp,\":\"); print(tmp[1]);}'"
}
function tgtadm_next_tid {
echo "$TGTADM --lld iscsi --op show --mode target | \
echo "$TGTADM --lld iscsi --op show --mode target | strings | \
$GREP \"Target\" | tail -n 1 | \
$AWK '{split(\$2,tmp,\":\"); print tmp[1]+1;}'"
}
@ -402,6 +403,30 @@ function iqn_get_vg_name {
echo $TARGET|$AWK -F. '{print $(NF-1)}'
}
function tgt_setup_lun_install {
DST_HOST="$1"
BASE_PATH="$2"
CHECK_FILE="$BASE_PATH/.tgt-setup-lun"
if [ ! -f "$CHECK_FILE" ]; then
$SSH "$DST_HOST" "$SUDO $TGTSETUPLUN" 2>&1 | \
$GREP -q "command not found"
if [ "$?" = "0" ]; then
error_message "$TGTSETUPLUN is not installed in $DST_HOST."
exit 127
else
touch "$CHECK_FILE"
fi
fi
}
function tgt_setup_lun {
IQN="$1"
DEV="$2"
echo "$TGTSETUPLUN -d $DEV -n $IQN 1>&2"
}
function iqn_get_host {
IQN="$1"
TARGET=`echo "$IQN"|$CUT -d: -f2`
@ -426,10 +451,10 @@ function vmfs_set_up {
if [ "$USE_SSH" != "yes" ]; then
USERNAME=`echo $(cat $VMWARERC |grep ":username:"|cut -d":" -f 3|tr -d '"')`
PASSWORD=`echo $(cat $VMWARERC |grep ":password:"|cut -d":" -f 3|tr -d '"')`
if [ -z $PASSWORD ]; then
VI_PARAMS="--server $DST_HOST --username $USERNAME --password \"\""
else
VI_PARAMS="--server $DST_HOST --username $USERNAME --password $PASSWORD"
if [ -z $PASSWORD ]; then
VI_PARAMS="--server $DST_HOST --username $USERNAME --password \"\""
else
VI_PARAMS="--server $DST_HOST --username $USERNAME --password $PASSWORD"
fi
fi
}

View File

@ -517,6 +517,8 @@ void Nebula::start()
time_t vm_expiration;
time_t host_expiration;
bool vm_submit_on_hold;
vector<const Attribute *> vm_hooks;
vector<const Attribute *> host_hooks;
vector<const Attribute *> vnet_hooks;
@ -543,12 +545,15 @@ void Nebula::start()
nebula_configuration->get("VM_MONITORING_EXPIRATION_TIME",vm_expiration);
nebula_configuration->get("HOST_MONITORING_EXPIRATION_TIME",host_expiration);
nebula_configuration->get("VM_SUBMIT_ON_HOLD",vm_submit_on_hold);
vmpool = new VirtualMachinePool(db,
vm_hooks,
hook_location,
remotes_location,
vm_restricted_attrs,
vm_expiration);
vm_expiration,
vm_submit_on_hold);
hpool = new HostPool(db,
host_hooks,
hook_location,

View File

@ -98,6 +98,7 @@ void OpenNebulaTemplate::set_conf_default()
# DB
# VNC_BASE_PORT
# SCRIPTS_REMOTE_DIR
# VM_SUBMIT_ON_HOLD
#*******************************************************************************
*/
// MONITOR_INTERVAL
@ -167,6 +168,12 @@ void OpenNebulaTemplate::set_conf_default()
attribute = new SingleAttribute("SCRIPTS_REMOTE_DIR",value);
conf_default.insert(make_pair(attribute->name(),attribute));
// VM_SUBMIT_ON_HOLD
value = "NO";
attribute = new SingleAttribute("VM_SUBMIT_ON_HOLD",value);
conf_default.insert(make_pair(attribute->name(),attribute));
/*
#*******************************************************************************
# Physical Networks configuration

View File

@ -129,16 +129,6 @@ public class Client{
return call("system.version");
}
/**
* Calls OpenNebula and retrieves oned configuration
*
* @return The server's xml-rpc response encapsulated
*/
public OneResponse get_config()
{
return call("system.config");
}
//--------------------------------------------------------------------------
// PRIVATE ATTRIBUTES AND METHODS
//--------------------------------------------------------------------------

View File

@ -32,12 +32,84 @@ public class OneSystem
private static final String GROUP_QUOTA_INFO = "groupquota.info";
private static final String GROUP_QUOTA_UPDATE = "groupquota.update";
public static final String VERSION = "3.9.0";
public OneSystem(Client client)
{
this.client = client;
}
/**
* Calls OpenNebula and retrieves the oned version
*
* @return The server's xml-rpc response encapsulated
*/
public OneResponse getOnedVersion()
{
return client.call("system.version");
}
/**
* Returns whether of not the oned version is the same as the OCA version
*
* @return true if oned is the same version
*/
public boolean compatibleVersion()
{
OneResponse r = getOnedVersion();
if (r.isError())
{
return false;
}
String[] ocaVersion = VERSION.split("\\.", 3);
String[] onedVersion = r.getMessage().split("\\.", 3);
return ocaVersion.length == onedVersion.length &&
ocaVersion[0].equals(onedVersion[0]) &&
ocaVersion[1].equals(onedVersion[1]);
}
/**
* Calls OpenNebula and retrieves oned configuration
*
* @return The server's xml-rpc response encapsulated
*/
public OneResponse getConfiguration()
{
return client.call("system.config");
}
/**
* Calls OpenNebula and retrieves oned configuration
*
* @return The xml root node in case of success, null otherwise
*/
public Node getConfigurationXML()
{
OneResponse r = getConfiguration();
Node xml = null;
if (r.isError())
{
return null;
}
try
{
DocumentBuilder builder =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(
new ByteArrayInputStream(r.getMessage().getBytes()));
xml = doc.getDocumentElement();
}
catch (Exception e) {}
return xml;
}
/**
* Gets the default user quota limits
*

View File

@ -65,6 +65,7 @@ public abstract class Document extends PoolElement
private static final String CHOWN = METHOD_PREFIX + "chown";
private static final String CHMOD = METHOD_PREFIX + "chmod";
private static final String CLONE = METHOD_PREFIX + "clone";
private static final String RENAME = METHOD_PREFIX + "rename";
/**
* Creates a new Document representation.
@ -215,6 +216,17 @@ public abstract class Document extends PoolElement
return client.call(CLONE, id, name);
}
/**
* Renames this document
*
* @param name New name for the document.
* @return If an error occurs the error message contains the reason.
*/
public OneResponse rename(String name)
{
return client.call(RENAME, id, name);
}
// =================================
// Helpers
// =================================

View File

@ -38,6 +38,7 @@ public class Image extends PoolElement
private static final String CHMOD = METHOD_PREFIX + "chmod";
private static final String CHTYPE = METHOD_PREFIX + "chtype";
private static final String CLONE = METHOD_PREFIX + "clone";
private static final String RENAME = METHOD_PREFIX + "rename";
private static final String[] IMAGE_STATES =
{"INIT", "READY", "USED", "DISABLED", "LOCKED",
@ -265,6 +266,19 @@ public class Image extends PoolElement
return client.call(CLONE, id, name);
}
/**
* Renames this Image
*
* @param client XML-RPC Client.
* @param id The Image id of the target Image.
* @param name New name for the Image.
* @return If an error occurs the error message contains the reason.
*/
public static OneResponse rename(Client client, int id, String name)
{
return client.call(RENAME, id, name);
}
// =================================
// Instanced object XML-RPC methods
// =================================
@ -498,6 +512,17 @@ public class Image extends PoolElement
return clone(client, id, name);
}
/**
* Renames this Image
*
* @param name New name for the Image.
* @return If an error occurs the error message contains the reason.
*/
public OneResponse rename(String name)
{
return rename(client, id, name);
}
// =================================
// Helpers
// =================================

View File

@ -36,6 +36,7 @@ public class Template extends PoolElement
private static final String CHMOD = METHOD_PREFIX + "chmod";
private static final String INSTANTIATE = METHOD_PREFIX + "instantiate";
private static final String CLONE = METHOD_PREFIX + "clone";
private static final String RENAME = METHOD_PREFIX + "rename";
/**
* Creates a new Template representation.
@ -199,11 +200,13 @@ public class Template extends PoolElement
* @param client XML-RPC Client.
* @param id The template id of the target template.
* @param name A string containing the name of the VM instance, can be empty.
* @param onHold False to create this VM in pending state, true on hold
* @return If successful the message contains the VM Instance ID.
*/
public static OneResponse instantiate(Client client, int id, String name)
public static OneResponse instantiate(Client client, int id, String name,
boolean onHold)
{
return client.call(INSTANTIATE, id, name);
return client.call(INSTANTIATE, id, name, onHold);
}
/**
@ -219,6 +222,19 @@ public class Template extends PoolElement
return client.call(CLONE, id, name);
}
/**
* Renames this Template
*
* @param client XML-RPC Client.
* @param id The Template id of the target Template.
* @param name New name for the Template.
* @return If an error occurs the error message contains the reason.
*/
public static OneResponse rename(Client client, int id, String name)
{
return client.call(RENAME, id, name);
}
// =================================
// Instanced object XML-RPC methods
// =================================
@ -368,6 +384,18 @@ public class Template extends PoolElement
return chmod(client, id, octet);
}
/**
* Creates a VM instance from a Template
*
* @param name A string containing the name of the VM instance, can be empty.
* @param onHold False to create this VM in pending state, true on hold
* @return If successful the message contains the VM Instance ID.
*/
public OneResponse instantiate(String name, boolean onHold)
{
return instantiate(client, id, name, onHold);
}
/**
* Creates a VM instance from a Template
*
@ -376,7 +404,7 @@ public class Template extends PoolElement
*/
public OneResponse instantiate(String name)
{
return instantiate(client, id, name);
return instantiate(client, id, name, false);
}
/**
@ -386,7 +414,7 @@ public class Template extends PoolElement
*/
public OneResponse instantiate()
{
return instantiate(client, id, "");
return instantiate(client, id, "", false);
}
/**
@ -400,6 +428,17 @@ public class Template extends PoolElement
return clone(client, id, name);
}
/**
* Renames this Template
*
* @param name New name for the Template.
* @return If an error occurs the error message contains the reason.
*/
public OneResponse rename(String name)
{
return rename(client, id, name);
}
// =================================
// Helpers
// =================================

View File

@ -39,6 +39,7 @@ public class VirtualMachine extends PoolElement{
private static final String MONITORING = METHOD_PREFIX + "monitoring";
private static final String ATTACH = METHOD_PREFIX + "attach";
private static final String DETACH = METHOD_PREFIX + "detach";
private static final String RENAME = METHOD_PREFIX + "rename";
private static final String[] VM_STATES =
{
@ -149,7 +150,22 @@ public class VirtualMachine extends PoolElement{
*/
public static OneResponse allocate(Client client, String description)
{
return client.call(ALLOCATE, description);
return allocate(client, description, false);
}
/**
* Allocates a new VM in OpenNebula.
*
* @param client XML-RPC Client.
* @param description A string containing the template of the vm.
* @param onHold False to create this VM in pending state, true on hold
* @return If successful the message contains the associated
* id generated for this VM.
*/
public static OneResponse allocate(Client client, String description,
boolean onHold)
{
return client.call(ALLOCATE, description, onHold);
}
/**
@ -273,6 +289,19 @@ public class VirtualMachine extends PoolElement{
return client.call(DETACH, id, diskId);
}
/**
* Renames this VM
*
* @param client XML-RPC Client.
* @param id The VM id of the target VM.
* @param name New name for the VM.
* @return If an error occurs the error message contains the reason.
*/
public static OneResponse rename(Client client, int id, String name)
{
return client.call(RENAME, id, name);
}
// =================================
// Instanced object XML-RPC methods
// =================================
@ -290,6 +319,21 @@ public class VirtualMachine extends PoolElement{
return response;
}
/**
* Initiates the instance of the VM on the target host.
*
* @param hostId The host id (hid) of the target host where
* the VM will be instantiated.
* @param enforce If it is set to true, the host capacity
* will be checked, and the deployment will fail if the host is
* overcommited. Defaults to false
* @return If an error occurs the error message contains the reason.
*/
public OneResponse deploy(int hostId, boolean enforce)
{
return client.call(DEPLOY, id, hostId, enforce);
}
/**
* Initiates the instance of the VM on the target host.
*
@ -299,7 +343,7 @@ public class VirtualMachine extends PoolElement{
*/
public OneResponse deploy(int hostId)
{
return client.call(DEPLOY, id, hostId);
return deploy(hostId, false);
}
/**
@ -337,11 +381,14 @@ public class VirtualMachine extends PoolElement{
* the vm.
* @param live If true we are indicating that we want livemigration,
* otherwise false.
* @param enforce If it is set to true, the host capacity
* will be checked, and the deployment will fail if the host is
* overcommited. Defaults to false
* @return If an error occurs the error message contains the reason.
*/
public OneResponse migrate(int hostId, boolean live)
public OneResponse migrate(int hostId, boolean live, boolean enforce)
{
return client.call(MIGRATE, id, hostId, live);
return client.call(MIGRATE, id, hostId, live, enforce);
}
/**
@ -486,6 +533,17 @@ public class VirtualMachine extends PoolElement{
return detachdisk(client, id, diskId);
}
/**
* Renames this VM
*
* @param name New name for the VM.
* @return If an error occurs the error message contains the reason.
*/
public OneResponse rename(String name)
{
return rename(client, id, name);
}
// =================================
// Helpers
// =================================
@ -628,6 +686,24 @@ public class VirtualMachine extends PoolElement{
return action("unresched");
}
/**
* Migrates the virtual machine to the target host (hid).
* <br/>
* It does the same as {@link VirtualMachine#migrate(int, boolean)}
* with live set to false.
*
* @param hostId The target host id (hid) where we want to migrate
* the vm.
* @param enforce If it is set to true, the host capacity
* will be checked, and the deployment will fail if the host is
* overcommited. Defaults to false
* @return If an error occurs the error message contains the reason.
*/
public OneResponse migrate(int hostId, boolean enforce)
{
return migrate(hostId, false, enforce);
}
/**
* Migrates the virtual machine to the target host (hid).
* <br/>
@ -643,6 +719,25 @@ public class VirtualMachine extends PoolElement{
return migrate(hostId, false);
}
/**
* Performs a live migration of the virtual machine to the
* target host (hid).
* <br/>
* It does the same as {@link VirtualMachine#migrate(int, boolean)}
* with live set to true.
*
* @param hostId The target host id (hid) where we want to migrate
* the vm.
* @param enforce If it is set to true, the host capacity
* will be checked, and the deployment will fail if the host is
* overcommited. Defaults to false
* @return If an error occurs the error message contains the reason.
*/
public OneResponse liveMigrate(int hostId, boolean enforce)
{
return migrate(hostId, true, enforce);
}
/**
* Performs a live migration of the virtual machine to the
* target host (hid).
@ -656,7 +751,7 @@ public class VirtualMachine extends PoolElement{
*/
public OneResponse liveMigrate(int hostId)
{
return migrate(hostId, true);
return liveMigrate(hostId, false);
}
public int state()

View File

@ -38,6 +38,7 @@ public class VirtualNetwork extends PoolElement{
private static final String UPDATE = METHOD_PREFIX + "update";
private static final String HOLD = METHOD_PREFIX + "hold";
private static final String RELEASE = METHOD_PREFIX + "release";
private static final String RENAME = METHOD_PREFIX + "rename";
/**
* Creates a new virtual network representation.
@ -263,7 +264,7 @@ public class VirtualNetwork extends PoolElement{
* Replaces the VirtualNetwork template contents.
*
* @param client XML-RPC Client.
* @param id The user id of the target vnet we want to modify.
* @param id The vnet id of the target vnet we want to modify.
* @param new_template New template contents.
* @return If successful the message contains the vnet id.
*/
@ -272,6 +273,19 @@ public class VirtualNetwork extends PoolElement{
return client.call(UPDATE, id, new_template);
}
/**
* Renames this VirtualNetwork
*
* @param client XML-RPC Client.
* @param id The VirtualNetwork id of the target VirtualNetwork.
* @param name New name for the VirtualNetwork.
* @return If an error occurs the error message contains the reason.
*/
public static OneResponse rename(Client client, int id, String name)
{
return client.call(RENAME, id, name);
}
// =================================
// Instanced object XML-RPC methods
// =================================
@ -491,6 +505,17 @@ public class VirtualNetwork extends PoolElement{
return update(client, id, new_template);
}
/**
* Renames this VirtualNetwork
*
* @param name New name for the VirtualNetwork.
* @return If an error occurs the error message contains the reason.
*/
public OneResponse rename(String name)
{
return rename(client, id, name);
}
// =================================
// Helpers
// =================================

View File

@ -1,12 +1,12 @@
/*******************************************************************************
* Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.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.
@ -17,6 +17,7 @@ import static org.junit.Assert.*;
import org.junit.Test;
import org.opennebula.client.*;
import org.w3c.dom.Node;
public class SessionTest {
@ -51,7 +52,7 @@ public class SessionTest {
}
assertNull("Client should complain about misspelled url", oneClient);
}
}
@Test
public void version()
@ -63,11 +64,24 @@ public class SessionTest {
}
catch (Exception e)
{
System.out.println(e.getMessage());
assertTrue( e.getMessage(), false );
}
OneResponse res = oneClient.get_version();
OneSystem system = new OneSystem(oneClient);
OneResponse res = system.getOnedVersion();
assertTrue( res.getErrorMessage(), !res.isError() );
res = system.getConfiguration();
assertTrue( res.getErrorMessage(), !res.isError() );
Node config = system.getConfigurationXML();
assertTrue( "XML configuration is null", config != null );
boolean compatible = system.compatibleVersion();
assertTrue(
"Incompatible version reported, " +
OneSystem.VERSION + ", " + system.getOnedVersion().getMessage(),
compatible );
}
}

View File

@ -172,9 +172,5 @@ module OpenNebula
def get_version()
call("system.version")
end
def get_config()
call("system.config")
end
end
end

View File

@ -44,6 +44,7 @@ module OpenNebula
:chown => "document.chown",
:chmod => "document.chmod",
:clone => "document.clone",
:rename => "document.rename"
}
# Creates a Document Object description with just its identifier
@ -185,6 +186,16 @@ module OpenNebula
return rc
end
# Renames this Document
#
# @param name [String] New name for the Document.
#
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def rename(name)
return call(DOCUMENT_METHODS[:rename], @pe_id, name)
end
#######################################################################
# Helpers to get Document information
#######################################################################

View File

@ -35,7 +35,8 @@ module OpenNebula
:chown => "image.chown",
:chmod => "image.chmod",
:chtype => "image.chtype",
:clone => "image.clone"
:clone => "image.clone",
:rename => "image.rename"
}
IMAGE_STATES=%w{INIT READY USED DISABLED LOCKED ERROR CLONE DELETE USED_PERS}
@ -205,6 +206,16 @@ module OpenNebula
return rc
end
# Renames this Image
#
# @param name [String] New name for the Image.
#
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def rename(name)
return call(IMAGE_METHODS[:rename], @pe_id, name)
end
#######################################################################
# Helpers to get Image information
#######################################################################

View File

@ -27,7 +27,9 @@ module OpenNebula
:userquotainfo => "userquota.info",
:userquotaupdate => "userquota.update",
:groupquotainfo => "groupquota.info",
:groupquotaupdate => "groupquota.update"
:groupquotaupdate => "groupquota.update",
:version => "system.version",
:config => "system.config"
}
#######################################################################
@ -44,6 +46,46 @@ module OpenNebula
# XML-RPC Methods
#######################################################################
# Gets the oned version
#
# @return [String, OpenNebula::Error] the oned version in case
# of success, Error otherwise
def get_oned_version()
return @client.call("system.version")
end
# Returns whether of not the oned version is the same as the OCA version
#
# @return [true, false, OpenNebula::Error] true if oned is the same
# version
def compatible_version()
no_revision = VERSION[/^\d+\.\d+\./]
oned_v = get_oned_version
if OpenNebula.is_error?(oned_v)
return oned_v
end
return (oned_v =~ /#{no_revision}/) != nil
end
# Gets the oned configuration
#
# @return [XMLElement, OpenNebula::Error] the oned configuration in case
# of success, Error otherwise
def get_configuration()
rc = @client.call(SYSTEM_METHODS[:config])
if OpenNebula.is_error?(rc)
return rc
end
config = XMLElement.new
config.initialize_xml(rc, 'TEMPLATE')
return config
end
# Gets the default user quota limits
#
# @return [XMLElement, OpenNebula::Error] the default user quota in case

View File

@ -32,7 +32,8 @@ module OpenNebula
:delete => "template.delete",
:chown => "template.chown",
:chmod => "template.chmod",
:clone => "template.clone"
:clone => "template.clone",
:rename => "template.rename"
}
# Creates a Template description with just its identifier
@ -85,13 +86,18 @@ module OpenNebula
# Creates a VM instance from a Template
#
# +name+ A string containing the name of the VM instance.
# [return] The new VM Instance ID, or an Error object
def instantiate(name="")
# @param name [String] Name for the VM instance. If it is an empty
# string OpenNebula will set a default name
# @param hold [true,false] false to create the VM in pending state,
# true to create it on hold
#
# @return [Integer, OpenNebula::Error] The new VM id, Error
# otherwise
def instantiate(name="", hold=false)
return Error.new('ID not defined') if !@pe_id
name ||= ""
rc = @client.call(TEMPLATE_METHODS[:instantiate], @pe_id, name)
rc = @client.call(TEMPLATE_METHODS[:instantiate], @pe_id, name, hold)
return rc
end
@ -157,6 +163,16 @@ module OpenNebula
return rc
end
# Renames this Template
#
# @param name [String] New name for the Template.
#
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def rename(name)
return call(TEMPLATE_METHODS[:rename], @pe_id, name)
end
#######################################################################
# Helpers to get Template information
#######################################################################

View File

@ -35,7 +35,8 @@ module OpenNebula
:chmod => "vm.chmod",
:monitoring => "vm.monitoring",
:attach => "vm.attach",
:detach => "vm.detach"
:detach => "vm.detach",
:rename => "vm.rename"
}
VM_STATE=%w{INIT PENDING HOLD ACTIVE STOPPED SUSPENDED DONE FAILED
@ -133,22 +134,29 @@ module OpenNebula
# Allocates a new VirtualMachine in OpenNebula
#
# +description+ A string containing the template of the VirtualMachine.
def allocate(description)
super(VM_METHODS[:allocate],description)
# @param description [String] A string containing the template of
# the VirtualMachine.
# @param hold [true,false] false to create the VM in pending state,
# true to create it on hold
#
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def allocate(description, hold=false)
super(VM_METHODS[:allocate], description, hold)
end
# Initiates the instance of the VM on the target host.
#
# +host_id+ The host id (hid) of the target host where
# the VM will be instantiated.
def deploy(host_id)
return Error.new('ID not defined') if !@pe_id
rc = @client.call(VM_METHODS[:deploy], @pe_id, host_id.to_i)
rc = nil if !OpenNebula.is_error?(rc)
return rc
# @param host_id [Interger] The host id (hid) of the target host where
# the VM will be instantiated.
# @param enforce [true|false] If it is set to true, the host capacity
# will be checked, and the deployment will fail if the host is
# overcommited. Defaults to false
#
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def deploy(host_id, enforce=false)
return call(VM_METHODS[:deploy], @pe_id, host_id.to_i, enforce)
end
# Shutdowns an already deployed VM
@ -247,23 +255,31 @@ module OpenNebula
end
# Saves a running VM and starts it again in the specified host
def migrate(host_id)
return Error.new('ID not defined') if !@pe_id
rc = @client.call(VM_METHODS[:migrate], @pe_id, host_id.to_i, false)
rc = nil if !OpenNebula.is_error?(rc)
return rc
#
# @param host_id [Interger] The host id (hid) of the target host where
# the VM will be migrated.
# @param enforce [true|false] If it is set to true, the host capacity
# will be checked, and the deployment will fail if the host is
# overcommited. Defaults to false
#
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def migrate(host_id, enforce=false)
return call(VM_METHODS[:migrate], @pe_id, host_id.to_i, false, enforce)
end
# Migrates a running VM to another host without downtime
def live_migrate(host_id)
return Error.new('ID not defined') if !@pe_id
rc = @client.call(VM_METHODS[:migrate], @pe_id, host_id.to_i, true)
rc = nil if !OpenNebula.is_error?(rc)
return rc
#
# @param host_id [Interger] The host id (hid) of the target host where
# the VM will be migrated.
# @param enforce [true|false] If it is set to true, the host capacity
# will be checked, and the deployment will fail if the host is
# overcommited. Defaults to false
#
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def live_migrate(host_id, enforce=false)
return call(VM_METHODS[:migrate], @pe_id, host_id.to_i, true, enforce)
end
# Set the specified vm's disk to be saved in a new image
@ -352,6 +368,16 @@ module OpenNebula
return @client.call(VM_METHODS[:monitoring], @pe_id)
end
# Renames this VM
#
# @param name [String] New name for the VM.
#
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def rename(name)
return call(VM_METHODS[:rename], @pe_id, name)
end
#######################################################################
# Helpers to get VirtualMachine information
#######################################################################

View File

@ -34,7 +34,8 @@ module OpenNebula
:chmod => "vn.chmod",
:update => "vn.update",
:hold => "vn.hold",
:release => "vn.release"
:release => "vn.release",
:rename => "vn.rename"
}
VN_TYPES=%w{RANGED FIXED}
@ -191,6 +192,16 @@ module OpenNebula
super(VN_METHODS[:chmod], owner_u, owner_m, owner_a, group_u,
group_m, group_a, other_u, other_m, other_a)
end
# Renames this virtual network
#
# @param name [String] New name for the virtual network.
#
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def rename(name)
return call(VN_METHODS[:rename], @pe_id, name)
end
#######################################################################
# Helpers to get VirtualNetwork information

View File

@ -364,6 +364,7 @@ void PoolSQL::update_cache_index(string& old_name,
int new_uid)
{
map<string,PoolObjectSQL *>::iterator index;
PoolObjectSQL * the_object;
lock();
@ -380,11 +381,13 @@ void PoolSQL::update_cache_index(string& old_name,
if ( index != name_pool.end() )
{
the_object = index->second;
name_pool.erase(old_key);
if ( name_pool.find(new_key) == name_pool.end())
{
name_pool.insert(make_pair(new_key, index->second));
name_pool.insert(make_pair(new_key, the_object));
}
}

View File

@ -26,6 +26,7 @@
#include "RequestManagerChown.h"
#include "RequestManagerChmod.h"
#include "RequestManagerClone.h"
#include "RequestManagerRename.h"
#include "RequestManagerVirtualNetwork.h"
#include "RequestManagerVirtualMachine.h"
@ -374,6 +375,13 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr group_get_default_quota(new GroupQuotaInfo());
xmlrpc_c::methodPtr group_set_default_quota(new GroupQuotaUpdate());
// Rename Methods
xmlrpc_c::methodPtr vm_rename(new VirtualMachineRename());
xmlrpc_c::methodPtr template_rename(new TemplateRename());
xmlrpc_c::methodPtr vn_rename(new VirtualNetworkRename());
xmlrpc_c::methodPtr image_rename(new ImageRename());
xmlrpc_c::methodPtr doc_rename(new DocumentRename());
/* VM related methods */
RequestManagerRegistry.addMethod("one.vm.deploy", vm_deploy);
RequestManagerRegistry.addMethod("one.vm.action", vm_action);
@ -386,6 +394,7 @@ void RequestManager::register_xml_methods()
RequestManagerRegistry.addMethod("one.vm.monitoring", vm_monitoring);
RequestManagerRegistry.addMethod("one.vm.attach", vm_attach);
RequestManagerRegistry.addMethod("one.vm.detach", vm_detach);
RequestManagerRegistry.addMethod("one.vm.rename", vm_rename);
RequestManagerRegistry.addMethod("one.vmpool.info", vm_pool_info);
RequestManagerRegistry.addMethod("one.vmpool.accounting", vm_pool_acct);
@ -400,6 +409,7 @@ void RequestManager::register_xml_methods()
RequestManagerRegistry.addMethod("one.template.chown", template_chown);
RequestManagerRegistry.addMethod("one.template.chmod", template_chmod);
RequestManagerRegistry.addMethod("one.template.clone", template_clone);
RequestManagerRegistry.addMethod("one.template.rename", template_rename);
RequestManagerRegistry.addMethod("one.templatepool.info",template_pool_info);
@ -436,6 +446,7 @@ void RequestManager::register_xml_methods()
RequestManagerRegistry.addMethod("one.vn.info", vn_info);
RequestManagerRegistry.addMethod("one.vn.chown", vn_chown);
RequestManagerRegistry.addMethod("one.vn.chmod", vn_chmod);
RequestManagerRegistry.addMethod("one.vn.rename", vn_rename);
RequestManagerRegistry.addMethod("one.vnpool.info", vnpool_info);
@ -465,6 +476,7 @@ void RequestManager::register_xml_methods()
RequestManagerRegistry.addMethod("one.image.chmod", image_chmod);
RequestManagerRegistry.addMethod("one.image.chtype", image_chtype);
RequestManagerRegistry.addMethod("one.image.clone", image_clone);
RequestManagerRegistry.addMethod("one.image.rename", image_rename);
RequestManagerRegistry.addMethod("one.imagepool.info", imagepool_info);
@ -506,6 +518,7 @@ void RequestManager::register_xml_methods()
RequestManagerRegistry.addMethod("one.document.chown", doc_chown);
RequestManagerRegistry.addMethod("one.document.chmod", doc_chmod);
RequestManagerRegistry.addMethod("one.document.clone", doc_clone);
RequestManagerRegistry.addMethod("one.document.rename", doc_rename);
RequestManagerRegistry.addMethod("one.documentpool.info",docpool_info);

View File

@ -238,13 +238,20 @@ int VirtualMachineAllocate::pool_allocate(xmlrpc_c::paramList const& paramList,
string& error_str,
RequestAttributes& att)
{
bool on_hold = false;
if ( paramList.size() > 2 )
{
on_hold = xmlrpc_c::value_boolean(paramList.getBoolean(2));
}
VirtualMachineTemplate * ttmpl= static_cast<VirtualMachineTemplate *>(tmpl);
VirtualMachinePool * vmpool = static_cast<VirtualMachinePool *>(pool);
Template tmpl_back(*tmpl);
int rc = vmpool->allocate(att.uid, att.gid, att.uname, att.gname, ttmpl, &id,
error_str, false);
error_str, on_hold);
if ( rc < 0 )
{

View File

@ -0,0 +1,113 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.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 "RequestManagerRename.h"
#include "PoolObjectSQL.h"
#include "NebulaLog.h"
#include "Nebula.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void RequestManagerRename::request_execute(xmlrpc_c::paramList const& paramList,
RequestAttributes& att)
{
int oid = xmlrpc_c::value_int(paramList.getInt(1));
string new_name = xmlrpc_c::value_string(paramList.getString(2));
int rc;
string old_name;
PoolObjectAuth operms;
PoolObjectSQL * object;
rc = get_info(pool, oid, auth_object, att, operms, old_name);
if ( rc == -1 )
{
return;
}
if (old_name == new_name)
{
success_response(oid, att);
return;
}
// ------------- Set authorization request for non-oneadmin's --------------
if ( att.uid != 0 )
{
AuthRequest ar(att.uid, att.gid);
ar.add_auth(auth_op, operms); // MANAGE OBJECT
if (UserPool::authorize(ar) == -1)
{
failure_response(AUTHORIZATION,
authorization_error(ar.message, att),
att);
return;
}
}
// --------------- Check name uniqueness -----------------------------------
object = get(new_name, operms.uid, true);
if ( object != 0 )
{
ostringstream oss;
int id = object->get_oid();
object->unlock();
oss << PoolObjectSQL::type_to_str(auth_object)
<< " cannot be renamed to " << new_name
<< " because it collides with "
<< PoolObjectSQL::type_to_str(auth_object) << " "
<< id;
failure_response(INTERNAL, request_error(oss.str(), ""), att);
return;
}
// --------------- Update the object ---------------------------------------
object = pool->get(oid, true);
if ( object == 0 )
{
failure_response(NO_EXISTS,
get_error(object_name(auth_object), oid),
att);
}
object->set_name(new_name);
pool->update(object);
object->unlock();
pool->update_cache_index(old_name, operms.uid, new_name, operms.uid);
success_response(oid, att);
return;
}

View File

@ -27,6 +27,13 @@ void VMTemplateInstantiate::request_execute(xmlrpc_c::paramList const& paramList
int id = xmlrpc_c::value_int(paramList.getInt(1));
string name = xmlrpc_c::value_string(paramList.getString(2));
bool on_hold = false;
if ( paramList.size() > 3 )
{
on_hold = xmlrpc_c::value_boolean(paramList.getBoolean(3));
}
int rc, vid;
PoolObjectAuth perms;
@ -109,7 +116,7 @@ void VMTemplateInstantiate::request_execute(xmlrpc_c::paramList const& paramList
Template tmpl_back(*tmpl);
rc = vmpool->allocate(att.uid, att.gid, att.uname, att.gname, tmpl, &vid,
error_str, false);
error_str, on_hold);
if ( rc < 0 )
{

View File

@ -200,6 +200,46 @@ int RequestManagerVirtualMachine::get_host_information(int hid,
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
bool RequestManagerVirtualMachine::check_host(int hid,
int cpu,
int mem,
int disk,
string& error)
{
Nebula& nd = Nebula::instance();
HostPool * hpool = nd.get_hpool();
Host * host;
bool test;
host = hpool->get(hid, true);
if (host == 0)
{
error = "Host no longer exists";
return false;
}
test = host->test_capacity(cpu, mem, disk);
if (!test)
{
ostringstream oss;
oss << object_name(PoolObjectSQL::HOST)
<< " " << hid << " does not have enough capacity.";
error = oss.str();
}
host->unlock();
return test;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
VirtualMachine * RequestManagerVirtualMachine::get_vm(int id,
RequestAttributes& att)
{
@ -387,31 +427,43 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
string ds_location;
int ds_id;
int id = xmlrpc_c::value_int(paramList.getInt(1));
int hid = xmlrpc_c::value_int(paramList.getInt(2));
int id = xmlrpc_c::value_int(paramList.getInt(1));
int hid = xmlrpc_c::value_int(paramList.getInt(2));
bool enforce = false;
if ( paramList.size() != 3 )
{
enforce = xmlrpc_c::value_boolean(paramList.getBoolean(3));
}
bool auth = false;
if (get_host_information(
hid, hostname, vmm_mad, vnm_mad, tm_mad, ds_location, ds_id, att,
host_perms) != 0)
if (get_host_information(hid,
hostname,
vmm_mad,
vnm_mad,
tm_mad,
ds_location,
ds_id,
att,
host_perms) != 0)
{
return;
}
auth = vm_authorization(id, 0, 0, att, &host_perms, 0, auth_op);
if ( auth == false )
if (auth == false)
{
return;
}
if ( (vm = get_vm(id, att)) == 0 )
if ((vm = get_vm(id, att)) == 0)
{
return;
}
if ( vm->get_state() != VirtualMachine::PENDING )
if (vm->get_state() != VirtualMachine::PENDING)
{
failure_response(ACTION,
request_error("Wrong state to perform action",""),
@ -421,8 +473,36 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
return;
}
if ( add_history(
vm,hid,hostname,vmm_mad,vnm_mad,tm_mad,ds_location,ds_id,att) != 0)
if (enforce)
{
int cpu, mem, disk;
string error;
vm->get_requirements(cpu, mem, disk);
vm->unlock();
if (check_host(hid, cpu, mem, disk, error) == false)
{
failure_response(ACTION, request_error(error,""), att);
return;
}
if ((vm = get_vm(id, att)) == 0)
{
return;
}
}
if (add_history(vm,
hid,
hostname,
vmm_mad,
vnm_mad,
tm_mad,
ds_location,
ds_id,
att) != 0)
{
vm->unlock();
return;
@ -459,27 +539,39 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
string aux_st;
int current_hid;
int id = xmlrpc_c::value_int(paramList.getInt(1));
int hid = xmlrpc_c::value_int(paramList.getInt(2));
bool live = xmlrpc_c::value_boolean(paramList.getBoolean(3));
int id = xmlrpc_c::value_int(paramList.getInt(1));
int hid = xmlrpc_c::value_int(paramList.getInt(2));
bool live = xmlrpc_c::value_boolean(paramList.getBoolean(3));
bool enforce = false;
if ( paramList.size() != 4 )
{
enforce = xmlrpc_c::value_boolean(paramList.getBoolean(4));
}
bool auth = false;
if (get_host_information(
hid, hostname, vmm_mad, vnm_mad, tm_mad, ds_location, ds_id, att,
host_perms) != 0)
if (get_host_information(hid,
hostname,
vmm_mad,
vnm_mad,
tm_mad,
ds_location,
ds_id,
att,
host_perms) != 0)
{
return;
}
auth = vm_authorization(id, 0, 0, att, &host_perms, 0, auth_op);
if ( auth == false )
if (auth == false)
{
return;
}
if ( (vm = get_vm(id, att)) == 0 )
if ((vm = get_vm(id, att)) == 0)
{
return;
}
@ -498,11 +590,35 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
current_hid = vm->get_hid();
vm->unlock();
if (enforce)
{
int cpu, mem, disk;
string error;
if (get_host_information(
current_hid, aux_st, aux_st, aux_st, aux_st, aux_st, current_ds_id,
att, aux_perms) != 0)
vm->get_requirements(cpu, mem, disk);
vm->unlock();
if (check_host(hid, cpu, mem, disk, error) == false)
{
failure_response(ACTION, request_error(error,""), att);
return;
}
}
else
{
vm->unlock();
}
if (get_host_information(current_hid,
aux_st,
aux_st,
aux_st,
aux_st,
aux_st,
current_ds_id,
att,
aux_perms) != 0)
{
return;
}
@ -529,14 +645,21 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
return;
}
if ( add_history(vm, hid, hostname, vmm_mad, vnm_mad, tm_mad, ds_location,
ds_id, att) != 0)
if (add_history(vm,
hid,
hostname,
vmm_mad,
vnm_mad,
tm_mad,
ds_location,
ds_id,
att) != 0)
{
vm->unlock();
return;
}
if ( live == true )
if (live == true)
{
dm->live_migrate(vm);
}

View File

@ -41,7 +41,8 @@ source_files=[
'RequestManagerChmod.cc',
'RequestManagerCluster.cc',
'RequestManagerClone.cc',
'RequestManagerSystem.cc'
'RequestManagerSystem.cc',
'RequestManagerRename.cc'
]
# Build library

View File

@ -112,27 +112,28 @@ int VirtualMachinePoolXML::dispatch(int vid, int hid, bool resched) const
try
{
//TODO Get live migration from config file
if (resched == true)
{
client->call(client->get_endpoint(), // serverUrl
"one.vm.migrate", // methodName
"siib", // arguments format
"siibb", // arguments format
&deploy_result, // resultP
client->get_oneauth().c_str(), // argument 0 (AUTH)
vid, // argument 1 (VM)
hid, // argument 2 (HOST)
live_resched); // argument 3 (LIVE)
live_resched, // argument 3 (LIVE)
false); // argument 4 (ENFORCE)
}
else
{
client->call(client->get_endpoint(), // serverUrl
"one.vm.deploy", // methodName
"sii", // arguments format
"siib", // arguments format
&deploy_result, // resultP
client->get_oneauth().c_str(), // argument 0 (AUTH)
vid, // argument 1 (VM)
hid); // argument 2 (HOST)
hid, // argument 2 (HOST)
false); // argument 3 (ENFORCE)
}
}
catch (exception const& e)

View File

@ -51,6 +51,7 @@ module OpenNebulaJSON
when "chmod" then self.chmod_octet(action_hash['params'])
when "hold" then self.hold(action_hash['params'])
when "release" then self.release(action_hash['params'])
when "rename" then self.rename(action_hash['params'])
else
error_msg = "#{action_hash['perform']} action not " <<
" available for this resource"
@ -85,5 +86,9 @@ module OpenNebulaJSON
def release(params=Hash.new)
super(params['ip'])
end
def rename(params=Hash.new)
super(params['name'])
end
end
end

View File

@ -589,6 +589,13 @@ var OpenNebula = {
},
"fetch_template" : function(params){
OpenNebula.Action.show(params,OpenNebula.Network.resource,"template");
},
"rename" : function(params){
var action_obj = params.data.extra_param;
OpenNebula.Action.simple_action(params,
OpenNebula.Network.resource,
"rename",
action_obj);
}
},

File diff suppressed because it is too large Load Diff

View File

@ -90,57 +90,69 @@ var create_datastore_tmpl =
</fieldset>\
</form></div>';
var update_datastore_tmpl =
'<form action="javascript:alert(\'js error!\');">\
<h3 style="margin-bottom:10px;">'+tr("Please, choose and modify the datastore you want to update")+':</h3>\
<fieldset style="border-top:none;">\
<label for="datastore_template_update_select">'+tr("Select a datastore")+':</label>\
<select id="datastore_template_update_select" name="datastore_template_update_select"></select>\
<div class="clear"></div>\
<div>\
<table class="permissions_table" style="padding:0 10px;">\
<thead><tr>\
<td style="width:130px">'+tr("Permissions")+':</td>\
<td style="width:40px;text-align:center;">'+tr("Use")+'</td>\
<td style="width:40px;text-align:center;">'+tr("Manage")+'</td>\
<td style="width:40px;text-align:center;">'+tr("Admin")+'</td></tr></thead>\
<tr>\
<td>'+tr("Owner")+'</td>\
<td style="text-align:center"><input type="checkbox" name="datastore_owner_u" class="owner_u" /></td>\
<td style="text-align:center"><input type="checkbox" name="datastore_owner_m" class="owner_m" /></td>\
<td style="text-align:center"><input type="checkbox" name="datastore_owner_a" class="owner_a" /></td>\
</tr>\
<tr>\
<td>'+tr("Group")+'</td>\
<td style="text-align:center"><input type="checkbox" name="datastore_group_u" class="group_u" /></td>\
<td style="text-align:center"><input type="checkbox" name="datastore_group_m" class="group_m" /></td>\
<td style="text-align:center"><input type="checkbox" name="datastore_group_a" class="group_a" /></td>\
</tr>\
<tr>\
<td>'+tr("Other")+'</td>\
<td style="text-align:center"><input type="checkbox" name="datastore_other_u" class="other_u" /></td>\
<td style="text-align:center"><input type="checkbox" name="datastore_other_m" class="other_m" /></td>\
<td style="text-align:center"><input type="checkbox" name="datastore_other_a" class="other_a" /></td>\
</tr>\
</table>\
</div>\
<label for="datastore_template_update_textarea">'+tr("Datastore")+':</label>\
<div class="clear"></div>\
<textarea id="datastore_template_update_textarea" style="width:100%; height:14em;"></textarea>\
</fieldset>\
<fieldset>\
<div class="form_buttons">\
<button class="button" id="datastore_template_update_button" value="Datastore.update_template">\
'+tr("Update")+'\
</button>\
</div>\
</fieldset>\
</form>';
var datastore_image_table_tmpl='<thead>\
<tr>\
<th class="check"><input type="checkbox" class="check_all" value="">'+tr("All")+'</input></th>\
<th>'+tr("ID")+'</th>\
<th>'+tr("Owner")+'</th>\
<th>'+tr("Group")+'</th>\
<th>'+tr("Name")+'</th>\
<th>'+tr("Datastore")+'</th>\
<th>'+tr("Size")+'</th>\
<th>'+tr("Type")+'</th>\
<th>'+tr("Registration time")+'</th>\
<th>'+tr("Persistent")+'</th>\
<th>'+tr("Status")+'</th>\
<th>'+tr("#VMS")+'</th>\
<th>'+tr("Target")+'</th>\
</tr>\
</thead>\
<tbody id="tbodyimages">\
</tbody>'
var datastores_select="";
var dataTable_datastores;
var $create_datastore_dialog;
/* -------- Image datatable -------- */
//Setup actions
var datastore_image_actions = {
"DatastoreImageInfo.list" : {
type: "list",
call: OpenNebula.Image.list,
callback: updateDatastoreImagesInfoView,
error: onError
}
}
//callback to update the list of images for Create dialog
function updateDatastoreImagesInfoView (request,image_list){
var image_list_array = [];
$.each(image_list,function(){
//Grab table data from the image_list
image_list_array.push(imageElementArray(this));
});
updateView(image_list_array,dataTable_datastore_images_panel);
}
//callback to update the list of images for info panel
function updateDatastoreimagesInfoView (request,image_list){
var image_list_array = [];
$.each(image_list,function(){
if(this.IMAGE.DATASTORE_ID == datastore_info.ID)
image_list_array.push(imageElementArray(this));
});
updateView(image_list_array,dataTable_datastore_images_panel);
}
//Setup actions
var datastore_actions = {
@ -187,29 +199,25 @@ var datastore_actions = {
error: onError
},
"Datastore.fetch_template" : {
type: "single",
call: OpenNebula.Datastore.fetch_template,
callback: function (request,response) {
$('#datastore_template_update_dialog #datastore_template_update_textarea').val(response.template);
},
error: onError
},
"Datastore.fetch_permissions" : {
type: "single",
call: OpenNebula.Datastore.show,
callback: function(request,element_json){
var dialog = $('#datastore_template_update_dialog form');
var ds = element_json.DATASTORE;
setPermissionsTable(ds,dialog);
setPermissionsTable(ds,$(".datastore_permissions_table"));
},
error: onError
},
"Datastore.update_dialog" : {
type: "custom",
call: popUpDatastoreTemplateUpdateDialog
"Datastore.update_template" : {
type: "single",
call: OpenNebula.Datastore.update,
callback: function(request) {
notifyMessage("Template updated correctly");
Sunstone.runAction('Datastore.showinfo',request.request.data[0]);
},
error: onError
},
"Datastore.update" : {
@ -309,12 +317,6 @@ var datastore_buttons = {
text: tr("+ New"),
condition: mustBeAdmin
},
"Datastore.update_dialog" : {
type: "action",
text: tr("Update properties"),
alwaysActive: true,
condition: mustBeAdmin
},
"Datastore.addtocluster" : {
type: "confirm_with_select",
text: tr("Select cluster"),
@ -351,11 +353,7 @@ var datastore_buttons = {
var datastore_info_panel = {
"datastore_info_tab" : {
title: tr("Datastore information"),
content: ""
},
"datastore_template_tab" : {
title: tr("Datastore template"),
title: tr("Information"),
content: ""
}
}
@ -370,6 +368,7 @@ var datastores_tab = {
}
Sunstone.addActions(datastore_actions);
Sunstone.addActions(datastore_image_actions);
Sunstone.addMainTab('datastores_tab',datastores_tab);
Sunstone.addInfoPanel('datastore_info_panel',datastore_info_panel);
@ -451,12 +450,9 @@ function updateDatastoreInfo(request,ds){
images_str=getImageName(info.IMAGES.ID);
};
var info_tab = {
title : tr("Datastore information"),
content:
'<table id="info_datastore_table" class="info_table" style="width:80%">\
var info_tab_content = '<table id="info_datastore_table" class="info_table">\
<thead>\
<tr><th colspan="2">'+tr("Datastore information")+' - '+info.NAME+'</th></tr>\
<tr><th colspan="2">'+tr("Information for Datastore")+' - '+info.NAME+'</th></tr>\
</thead>\
<tbody>\
<tr>\
@ -491,39 +487,74 @@ function updateDatastoreInfo(request,ds){
<td class="key_td">'+tr("Base path")+'</td>\
<td class="value_td">'+info.BASE_PATH+'</td>\
</tr>\
<tr>\
<td class="key_td">'+tr("Images")+'</td>\
<td class="value_td">'+images_str+'</td>\
</tr>\
<tr><td class="key_td">'+tr("Permissions")+'</td><td></td></tr>\
<tr>\
<td class="key_td">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'+tr("Owner")+'</td>\
<td class="value_td" style="font-family:monospace;">'+ownerPermStr(info)+'</td>\
</tr>\
<tr>\
<td class="key_td">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'+tr("Group")+'</td>\
<td class="value_td" style="font-family:monospace;">'+groupPermStr(info)+'</td>\
</tr>\
<tr>\
<td class="key_td"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'+tr("Other")+'</td>\
<td class="value_td" style="font-family:monospace;">'+otherPermStr(info)+'</td>\
</tr>\
</tbody>\
</table>'
</table>';
// Inserts the extended template table to the show info tab (down tab)
info_tab_content += insert_extended_template_table(info.TEMPLATE,
"Datastore",
info.ID)
// Inserts the change permissions table
info_tab_content += insert_permissions_table("Datastore",info.ID);
var info_tab = {
title : tr("Information"),
content: info_tab_content
}
var template_tab = {
title: tr("Datastore Template"),
content:
'<table id="datastore_template_table" class="info_table" style="width:80%">\
<thead><tr><th colspan="2">'+tr("Datastore template")+'</th></tr></thead>'+
prettyPrintJSON(info.TEMPLATE)+
'</table>'
var datastore_info_tab = {
title: tr("Images"),
content : '<div id="datatable_datastore_images_info_div"><table id="datatable_datastore_images_info_panel" class="display">' + datastore_image_table_tmpl + '</table></div>'
}
// Add tabs
Sunstone.updateInfoPanelTab("datastore_info_panel","datastore_info_tab",info_tab);
Sunstone.updateInfoPanelTab("datastore_info_panel","datastore_template_tab",template_tab);
Sunstone.updateInfoPanelTab("datastore_info_panel","datastore_image_tab",datastore_info_tab);
Sunstone.popUpInfoPanel("datastore_info_panel");
// Define datatables
// Images datatable
dataTable_datastore_images_panel = $("#datatable_datastore_images_info_panel").dataTable({
"bJQueryUI": true,
"bSortClasses": false,
"bAutoWidth":false,
"sDom" : '<"H"lfrC>t<"F"ip>',
"oColVis": {
"aiExclude": [ 0 ]
},
"sPaginationType": "full_numbers",
"aoColumnDefs": [
{ "bSortable": false, "aTargets": ["check"] },
{ "sWidth": "60px", "aTargets": [0,2,3,9,10] },
{ "sWidth": "35px", "aTargets": [1,6,11,12] },
{ "sWidth": "100px", "aTargets": [5,7] },
{ "sWidth": "150px", "aTargets": [8] },
{ "bVisible": false, "aTargets": [6,8,12]}
],
"oLanguage": (datatable_lang != "") ?
{
sUrl: "locale/"+lang+"/"+datatable_lang
} : ""
});
//preload it
dataTable_datastore_images_panel.fnClearTable();
addElement([
spinner,
'','','','','','','','','','','',''],dataTable_datastore_images_panel);
// initialize datatables values
Sunstone.runAction("DatastoreImageInfo.list");
Sunstone.runAction("Datastore.fetch_permissions",info.ID);
}
// Set up the create datastore dialog
@ -593,107 +624,6 @@ function popUpCreateDatastoreDialog(){
$create_datastore_dialog.dialog('open');
}
function setupDatastoreTemplateUpdateDialog(){
//Append to DOM
dialogs_context.append('<div id="datastore_template_update_dialog" title="'+tr("Update Datastore properties")+'"></div>');
var dialog = $('#datastore_template_update_dialog',dialogs_context);
//Put HTML in place
dialog.html(update_datastore_tmpl);
var height = Math.floor($(window).height()*0.8); //set height to a percentage of the window
//Convert into jQuery
dialog.dialog({
autoOpen:false,
width:500,
modal:true,
height:height,
resizable:true
});
$('button',dialog).button();
$('#datastore_template_update_select',dialog).change(function(){
var id = $(this).val();
$('.permissions_table input',dialog).removeAttr('checked');
$('.permissions_table',dialog).removeAttr('update');
if (id && id.length){
var dialog = $('#datastore_template_update_dialog');
$('#template_template_update_textarea',dialog).val(tr("Loading")+"...");
Sunstone.runAction("Datastore.fetch_template",id);
Sunstone.runAction("Datastore.fetch_permissions",id);
} else {
$('#datastore_template_update_textarea',dialog).val("");
};
});
$('.permissions_table input',dialog).change(function(){
$(this).parents('table').attr('update','update');
});
$('form',dialog).submit(function(){
var dialog = $(this);
var new_template = $('#datastore_template_update_textarea',dialog).val();
var id = $('#datastore_template_update_select',dialog).val();
if (!id || !id.length) {
$(this).parents('#datastore_template_update_dialog').dialog('close');
return false;
};
var permissions = $('.permissions_table',dialog);
if (permissions.attr('update')){
var perms = {
octet : buildOctet(permissions)
};
Sunstone.runAction("Datastore.chmod",id,perms);
};
Sunstone.runAction("Datastore.update",id,new_template);
$(this).parents('#datastore_template_update_dialog').dialog('close');
return false;
});
};
// Standard template edition dialog
// If one element is selected auto fecth template
// otherwise let user select
function popUpDatastoreTemplateUpdateDialog(){
var select = makeSelectOptions(dataTable_datastores,
1,//id_col
4,//name_col
[],
[]
);
var sel_elems = getSelectedNodes(dataTable_datastores);
var dialog = $('#datastore_template_update_dialog');
$('#datastore_template_update_select',dialog).html(select);
$('#datastore_template_update_textarea',dialog).val("");
$('.permissions_table input',dialog).removeAttr('checked');
$('.permissions_table',dialog).removeAttr('update');
if (sel_elems.length >= 1){ //several items in the list are selected
//grep them
var new_select= sel_elems.length > 1? '<option value="">Please select</option>' : "";
$('option','<select>'+select+'</select>').each(function(){
var val = $(this).val();
if ($.inArray(val,sel_elems) >= 0){
new_select+='<option value="'+val+'">'+$(this).text()+'</option>';
};
});
$('#datastore_template_update_select',dialog).html(new_select);
if (sel_elems.length == 1) {
$('#datastore_template_update_select option',dialog).attr('selected','selected');
$('#datastore_template_update_select',dialog).trigger("change");
};
};
dialog.dialog('open');
return false;
};
//Prepares autorefresh
function setDatastoreAutorefresh(){
setInterval(function(){
@ -738,7 +668,6 @@ $(document).ready(function(){
Sunstone.runAction("Datastore.list");
setupCreateDatastoreDialog();
setupDatastoreTemplateUpdateDialog();
setDatastoreAutorefresh();
initCheckAllBoxes(dataTable_datastores);

View File

@ -243,34 +243,12 @@ var host_actions = {
error: hostMonitorError
},
"Host.fetch_template" : {
type: "single",
call: OpenNebula.Host.fetch_template,
callback: function (request,response) {
$('#template_update_dialog #template_update_textarea').val(response.template);
},
error: onError
},
"Host.update_dialog" : {
type: "custom",
call: function() {
popUpTemplateUpdateDialog("Host",
makeSelectOptions(dataTable_hosts,
1,//id_col
2,//name_col
[],
[]
),
getSelectedNodes(dataTable_hosts));
}
},
"Host.update" : {
"Host.update_template" : {
type: "single",
call: OpenNebula.Host.update,
callback: function() {
callback: function(request) {
notifyMessage(tr("Template updated correctly"));
Sunstone.runAction('Host.showinfo',request.request.data[0]);
},
error: onError
},
@ -319,12 +297,7 @@ var host_buttons = {
text: tr("+ New"),
condition: mustBeAdmin
},
"Host.update_dialog" : {
type: "action",
text: tr("Update a template"),
alwaysActive: true,
condition: mustBeAdmin
},
"Host.addtocluster" : {
type: "confirm_with_select",
text: tr("Select cluster"),
@ -571,53 +544,53 @@ function hostElementArray(host_json){
// Generate CPU progress bars
var max_cpu = parseInt(host.HOST_SHARE.MAX_CPU);
if (!max_cpu) {
if (!max_cpu) {
max_cpu = 100
}
var allocated_cpu = parseInt(host.HOST_SHARE.CPU_USAGE);
var ratio_allocated_cpu = Math.round((allocated_cpu / max_cpu) * 100);
var pb_allocated_cpu = progressBar(ratio_allocated_cpu, {
var pb_allocated_cpu = progressBar(ratio_allocated_cpu, {
label: allocated_cpu + ' / ' + max_cpu + ' (' + ratio_allocated_cpu + '%)',
width: '150px',
height: '15px',
width: '150px',
height: '15px',
fontSize: '1em' });
var real_cpu = parseInt(host.HOST_SHARE.USED_CPU);
var ratio_real_cpu = Math.round((real_cpu / max_cpu) * 100);
var pb_real_cpu = progressBar(ratio_real_cpu, {
var pb_real_cpu = progressBar(ratio_real_cpu, {
label: real_cpu + ' / ' + max_cpu + ' (' + ratio_real_cpu + '%)',
width: '150px',
height: '15px',
width: '150px',
height: '15px',
fontSize: '1em'});
// Generate MEM progress bars
var max_mem = parseInt(host.HOST_SHARE.MAX_MEM);
if (!max_mem) {
if (!max_mem) {
max_mem = 100
}
var allocated_mem = parseInt(host.HOST_SHARE.MEM_USAGE);
var ratio_allocated_mem = Math.round((allocated_mem / max_mem) * 100);
var pb_allocated_mem = progressBar(ratio_allocated_mem, {
var pb_allocated_mem = progressBar(ratio_allocated_mem, {
label: humanize_size(allocated_mem) + ' / ' + humanize_size(max_mem) + ' (' + ratio_allocated_mem + '%)',
width: '150px',
height: '15px',
width: '150px',
height: '15px',
fontSize: '1em' });
var real_mem = parseInt(host.HOST_SHARE.USED_MEM);
var ratio_real_mem = Math.round((real_mem / max_mem) * 100);
var pb_real_mem = progressBar(ratio_real_mem, {
var pb_real_mem = progressBar(ratio_real_mem, {
label: humanize_size(real_mem) + ' / ' + humanize_size(max_mem) + ' (' + ratio_real_mem + '%)',
width: '150px',
height: '15px',
width: '150px',
height: '15px',
fontSize: '1em' });
@ -697,11 +670,11 @@ function updateHostInfo(request,host){
//Information tab
var info_tab = {
title : tr("Host information"),
title : tr("Information"),
content :
'<table id="info_host_table" class="info_table">\
<thead>\
<tr><th colspan="2">' + tr("Host information") + ' - '+host_info.NAME+'</th></tr>\
<tr><th colspan="2">' + tr("Information for Host") + ' - '+host_info.NAME+'</th></tr>\
</thead>\
<tbody>\
<tr>\
@ -768,18 +741,11 @@ function updateHostInfo(request,host){
<td class="value_td">'+host_info.HOST_SHARE.RUNNING_VMS+'</td>\
</tr>\
</tbody>\
</table>'
</table>' + insert_extended_template_table(host_info.TEMPLATE,
"Host",
host_info.ID)
}
//Template tab
var template_tab = {
title : tr("Host template"),
content :
'<table id="host_template_table" class="info_table" style="width:80%">\
<thead><tr><th colspan="2">' + tr("Host template") + '</th></tr></thead>'+
prettyPrintJSON(host_info.TEMPLATE)+
'</table>'
}
var monitor_tab = {
title: tr("Monitoring information"),
@ -788,7 +754,6 @@ function updateHostInfo(request,host){
//Sunstone.updateInfoPanelTab(info_panel_name,tab_name, new tab object);
Sunstone.updateInfoPanelTab("host_info_panel","host_info_tab",info_tab);
Sunstone.updateInfoPanelTab("host_info_panel","host_template_tab",template_tab);
Sunstone.updateInfoPanelTab("host_info_panel","host_monitoring_tab",monitor_tab);
Sunstone.popUpInfoPanel("host_info_panel");

View File

@ -355,36 +355,33 @@ var vnet_actions = {
notify: true
},
"Network.fetch_template" : {
"Network.rename" : {
type: "single",
call: OpenNebula.Network.fetch_template,
callback: function (request,response) {
$('#vnet_template_update_dialog #vnet_template_update_textarea').val(response.template);
call: OpenNebula.Network.rename,
callback: function(request) {
notifyMessage("VirtualNetwork renamed correctly");
Sunstone.runAction('Network.showinfo',request.request.data[0]);
},
error: onError
error: onError,
notify: true
},
"Network.fetch_permissions" : {
type: "single",
call: OpenNebula.Network.show,
callback: function(request,vnet_json){
var dialog = $('#vnet_template_update_dialog form');
var vnet = vnet_json.VNET;
setPermissionsTable(vnet,dialog);
setPermissionsTable(vnet,$(".network_permissions_table"));
},
error: onError
},
"Network.update_dialog" : {
type: "custom",
call: popUpVNetTemplateUpdateDialog
},
"Network.update" : {
"Network.update_template" : {
type: "single",
call: OpenNebula.Network.update,
callback: function() {
callback: function(request) {
notifyMessage("Template updated correctly");
Sunstone.runAction('Network.showinfo',request.request.data[0]);
},
error: onError
},
@ -434,11 +431,6 @@ var vnet_buttons = {
text: tr("+ New")
},
"Network.update_dialog" : {
type: "action",
text: tr("Update properties"),
alwaysActive: true
},
"Network.addtocluster" : {
type: "confirm_with_select",
text: tr("Select cluster"),
@ -566,8 +558,8 @@ function updateVNetworkInfo(request,vn){
var info_tab_content =
'<table id="info_vn_table" class="info_table">\
<thead>\
<tr><th colspan="2">'+tr("Virtual Network")+' '+vn_info.ID+' '+
tr("information")+'</th></tr>\
<tr><th colspan="2">'+tr("Information for Virtual Network")+' - '+vn_info.NAME+' '+
'</th></tr>\
</thead>\
<tr>\
<td class="key_td">'+tr("ID")+'</td>\
@ -575,7 +567,11 @@ function updateVNetworkInfo(request,vn){
</tr>\
<tr>\
<td class="key_td">'+tr("Name")+'</td>\
<td class="value_td">'+vn_info.NAME+'</td>\
<td class="value_td_rename">'+vn_info.NAME+'</td>\
<td><div id="div_edit_rename">\
<a id="div_edit_rename_link" class="edit_e" href="#">e</a>\
</div>\
</td>\
</tr>\
<tr>\
<td class="key_td">'+tr("Cluster")+'</td>\
@ -605,30 +601,17 @@ function updateVNetworkInfo(request,vn){
<td class="key_td">'+tr("VLAN ID")+'</td>\
<td class="value_td">'+ (typeof(vn_info.VLAN_ID) == "object" ? "--": vn_info.VLAN_ID) +'</td>\
</tr>\
<tr><td class="key_td">'+tr("Permissions")+'</td><td></td></tr>\
<tr>\
<td class="key_td">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'+tr("Owner")+'</td>\
<td class="value_td" style="font-family:monospace;">'+ownerPermStr(vn_info)+'</td>\
</tr>\
<tr>\
<td class="key_td">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'+tr("Group")+'</td>\
<td class="value_td" style="font-family:monospace;">'+groupPermStr(vn_info)+'</td>\
</tr>\
<tr>\
<td class="key_td"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'+tr("Other")+'</td>\
<td class="value_td" style="font-family:monospace;">'+otherPermStr(vn_info)+'</td>\
</tr>\
</table>';
info_tab_content += '\
<table id="vn_template_table" class="info_table">\
<thead><tr><th colspan="2">'+tr("Virtual Network template (attributes)")+'</th></tr></thead>'+
prettyPrintJSON(vn_info.TEMPLATE)+
'</table>';
info_tab_content += insert_extended_template_table(vn_info.TEMPLATE,
"Network",
vn_info.ID);
info_tab_content += insert_permissions_table("Network",vn_info.ID);
var info_tab = {
title: tr("Virtual Network information"),
title: tr("Information"),
content: info_tab_content
};
@ -637,11 +620,33 @@ function updateVNetworkInfo(request,vn){
content: printLeases(vn_info)
};
$("#div_edit_link").die();
$(".div_edit_rename_link").die();
// Listener for key,value pair edit action
$("#div_edit_rename_link").live("click", function() {
var value_str = $(".value_td_rename").text();
$(".value_td_rename").html('<input class="input_edit_value_rename" id="input_edit_rename" type="text" value="'+value_str+'"/>');
});
$(".input_edit_value_rename").live("change", function() {
var value_str = $(".input_edit_value_rename").val();
if(value_str!="")
{
// Let OpenNebula know
var name_template = {"name": value_str};
Sunstone.runAction("Network.rename",vn_info.ID,name_template);
}
});
Sunstone.updateInfoPanelTab("vnet_info_panel","vnet_info_tab",info_tab);
Sunstone.updateInfoPanelTab("vnet_info_panel","vnet_leases_tab",leases_tab);
Sunstone.popUpInfoPanel("vnet_info_panel");
Sunstone.runAction("Network.fetch_permissions",vn_info.ID);
}
// Prints the lis of leases depending on the Vnet TYPE
@ -1023,109 +1028,6 @@ function popUpCreateVnetDialog() {
}
function setupVNetTemplateUpdateDialog(){
//Append to DOM
dialogs_context.append('<div id="vnet_template_update_dialog" title="'+tr("Update network properties")+'"></div>');
var dialog = $('#vnet_template_update_dialog',dialogs_context);
//Put HTML in place
dialog.html(update_vnet_tmpl);
var height = Math.floor($(window).height()*0.8); //set height to a percentage of the window
//Convert into jQuery
dialog.dialog({
autoOpen:false,
width:700,
modal:true,
height:height,
resizable:true
});
$('button',dialog).button();
$('#vnet_template_update_select',dialog).change(function(){
var id = $(this).val();
$('.permissions_table input',dialog).removeAttr('checked')
$('.permissions_table',dialog).removeAttr('update');
if (id && id.length){
var dialog = $('#vnet_template_update_dialog');
$('#vnet_template_update_textarea',dialog).val(tr("Loading")+"...");
Sunstone.runAction("Network.fetch_permissions",id);
Sunstone.runAction("Network.fetch_template",id);
} else {
$('#vnet_template_update_textarea',dialog).val("");
};
});
$('.permissions_table input',dialog).change(function(){
$(this).parents('table').attr('update','update');
});
$('form',dialog).submit(function(){
var dialog = $(this);
var new_template = $('#vnet_template_update_textarea',dialog).val();
var id = $('#vnet_template_update_select',dialog).val();
if (!id || !id.length) {
$(this).parents('#vnet_template_update_dialog').dialog('close');
return false;
};
var permissions = $('.permissions_table',dialog);
if (permissions.attr('update')){
var perms = {
octet : buildOctet(permissions)
};
Sunstone.runAction("Network.chmod",id,perms);
};
Sunstone.runAction("Network.update",id,new_template);
$(this).parents('#vnet_template_update_dialog').dialog('close');
return false;
});
};
// When 1 elem in the list is selected then fetch template automaticly
// Otherwise include selected elements in the select and let user choose
function popUpVNetTemplateUpdateDialog(){
var select = makeSelectOptions(dataTable_vNetworks,
1,//id_col
4,//name_col
[],
[]
);
var sel_elems = getSelectedNodes(dataTable_vNetworks);
var dialog = $('#vnet_template_update_dialog');
$('#vnet_template_update_select',dialog).html(select);
$('#vnet_template_update_textarea',dialog).val("");
$('.permissions_table input',dialog).removeAttr('checked');
$('.permissions_table',dialog).removeAttr('update');
if (sel_elems.length >= 1){ //several items in the list are selected
//grep them
var new_select= sel_elems.length > 1? '<option value="">Please select</option>' : "";
$('option','<select>'+select+'</select>').each(function(){
var val = $(this).val();
if ($.inArray(val,sel_elems) >= 0){
new_select+='<option value="'+val+'">'+$(this).text()+'</option>';
};
});
$('#vnet_template_update_select',dialog).html(new_select);
if (sel_elems.length == 1) {
$('#vnet_template_update_select option',dialog).attr('selected','selected');
$('#vnet_template_update_select',dialog).trigger("change");
};
};
dialog.dialog('open');
return false;
}
// Listeners to the add, hold, release, delete leases operations in the
// extended information panel.
function setupLeasesOps(){
@ -1228,7 +1130,6 @@ $(document).ready(function(){
Sunstone.runAction("Network.list");
setupCreateVNetDialog();
setupVNetTemplateUpdateDialog();
setupLeasesOps();
setVNetAutorefresh();

View File

@ -237,7 +237,7 @@ function notifyMessage(msg){
// Returns an HTML string with the json keys and values
// Attempts to css format output, giving different values to
// margins etc. according to depth level etc.
// See exapmle of use in plugins.
// See example of use in plugins.
function prettyPrintJSON(template_json,padding,weight, border_bottom,padding_top_bottom){
var str = ""
if (!template_json){ return "Not defined";}
@ -1217,7 +1217,7 @@ function quotaListItem(quota_json){
*/
function progressBar(value, opts){
if (value > 100) value = 100;
if (!opts) opts = {};
if (!opts.width) opts.width = 'auto';
@ -1261,4 +1261,174 @@ function loadAccounting(resource, id, graphs, options){
graph_cfg.show_date = (end - start) > (3600 * 24)? true : false;
Sunstone.runAction(resource+".accounting", id, graph_cfg);
};
}
function insert_extended_template_table(template_json,resource_type,resource_id)
{
var str = '<table id="'+resource_type.toLowerCase()+'_template_table" class="info_table">\
<thead>\
<tr>\
<th colspan="2">' +
tr("Extended Template") +
'</th>\
</tr>\
</thead>\
<tr>\
<td class="key_td"><input type="text" name="new_key" id="new_key" /></td>\
<td class="value_td"><input type="text" name="new_value" id="new_value" /></td>\
<td class=""><button id="button_add_value">'+tr("Add")+'</button>\</td>\
</tr>' + fromJSONtoHTMLTable(template_json,
resource_type,
resource_id) +
'</table>'
// Remove previous listeners
$("#new_key").die();
$("#new_value").die();
$("#div_minus").die();
$("#div_edit").die();
$(".input_edit_value").die();
$("button").die();
// Add listener for add key and add value for Extended Template
$('button').live("click", function() {
if ( $('#new_value').val() != "" && $('#new_key').val() != "" )
{
template_json[$('#new_key').val()] = $('#new_value').val();
var template_str = "";
for(var key in template_json)
template_str=template_str+key+"="+ template_json[key]+"\n";
Sunstone.runAction(resource_type+".update_template",resource_id,template_str);
}
});
// Listener for key,value pair remove action
$("#div_minus").live("click", function() {
// Remove div_minus_ from the id
field=this.firstElementChild.id.substring(10,this.firstElementChild.id.length);
// Erase the value from the template
delete template_json[tr(field)];
// Convert from hash to string
var template_str = "\n";
for(var key in template_json)
template_str=template_str+key+"="+ template_json[key]+"\n";
// Let OpenNebula know
Sunstone.runAction(resource_type+".update_template",resource_id,template_str);
});
// Listener for key,value pair edit action
$("#div_edit").live("click", function() {
var key_str=this.firstElementChild.id.substring(9,this.firstElementChild.id.length);
var value_str = $("#value_td_input_"+key_str).text();
$("#value_td_input_"+key_str).html('<input class="input_edit_value" id="input_edit_'+key_str+'" type="text" value="'+value_str+'"/>');
});
$(".input_edit_value").live("change", function() {
var key_str = this.id.substring(11,this.id.length);
var value_str = this.value;
delete template_json[key_str];
template_json[key_str]=value_str;
// Convert from hash to string
var template_str = "\n";
for(var key in template_json)
template_str=template_str+key+"="+ template_json[key]+"\n";
// Let OpenNebula know
Sunstone.runAction(resource_type+".update_template",resource_id,template_str);
});
return str;
}
// Returns an HTML string with the json keys and values
function fromJSONtoHTMLTable(template_json,resource_type,resource_id){
var str = ""
if (!template_json){ return "Not defined";}
var field = null;
if (template_json.constructor == Array){
for (field = 0; field < template_json.length; ++field){
str += fromJSONtoHTMLRow(field,
template_json[field],
template_json,
resource_type,
resource_id);
}
} else {
for (field in template_json) {
str += fromJSONtoHTMLRow(field,
template_json[field],
template_json,
resource_type,
resource_id);
}
}
return str;
}
// Helper for fromJSONtoHTMLTable function
function fromJSONtoHTMLRow(field,value,template_json,resource_type,resource_id){
var str = '<tr>\
<td class="key_td">'+tr(field)+'</td>\
<td class="value_td" id="value_td_input_'+tr(field)+'">'+value+'</td>\
<td><div id="div_edit">\
<a id="div_edit_'+tr(field)+'" class="edit_e" href="#">e</a>\
</div>\
</td>\
<td><div id="div_minus">\
<a id="div_minus_'+tr(field)+'" class="remove_x" href="#">x</a>\
</div>\
</td>\
</tr>';
return str;
}
// Returns HTML with listeners to control permissions
function insert_permissions_table(resource_type,resource_id){
var str ='<table class="'+resource_type.toLowerCase()+'_permissions_table" style="padding:0 10px;">\
<thead><tr>\
<td style="width:130px">'+tr("Permissions")+':</td>\
<td style="width:40px;text-align:center;">'+tr("Use")+'</td>\
<td style="width:40px;text-align:center;">'+tr("Manage")+'</td>\
<td style="width:40px;text-align:center;">'+tr("Admin")+'</td></tr></thead>\
<tr>\
<td>'+tr("Owner")+'</td>\
<td style="text-align:center"><input type="checkbox" name="vnet_owner_u" class="permission_check owner_u" /></td>\
<td style="text-align:center"><input type="checkbox" name="vnet_owner_m" class="permission_check owner_m" /></td>\
<td style="text-align:center"><input type="checkbox" name="vnet_owner_a" class="permission_check owner_a" /></td>\
</tr>\
<tr>\
<td>'+tr("Group")+'</td>\
<td style="text-align:center"><input type="checkbox" name="vnet_owner_u" class="permission_check group_u" /></td>\
<td style="text-align:center"><input type="checkbox" name="vnet_group_m" class="permission_check group_m" /></td>\
<td style="text-align:center"><input type="checkbox" name="vnet_group_a" class="permission_check group_a" /></td>\
</tr>\
<tr>\
<td>'+tr("Other")+'</td>\
<td style="text-align:center"><input type="checkbox" name="vnet_other_u" class="permission_check other_u" /></td>\
<td style="text-align:center"><input type="checkbox" name="vnet_other_m" class="permission_check other_m" /></td>\
<td style="text-align:center"><input type="checkbox" name="vnet_other_a" class="permission_check other_a" /></td>\
</tr>\
</table>'
$(".permission_check").die();
$(".permission_check").live('change',function(){
var permissions_table = $("."+resource_type.toLowerCase()+"_permissions_table");
var permissions_octect = { octet : buildOctet(permissions_table) };
Sunstone.runAction(resource_type+".chmod",resource_id,permissions_octect);
});
return str;
}

View File

@ -326,6 +326,16 @@ hr{margin:18px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff
<% end %>
<!-- End User Plugins -->
<style>
.ui-tabs-vertical { width: 55em; }
.ui-tabs-vertical .ui-tabs-nav { padding: .2em .1em .2em .2em; float: left; width: 12em; }
.ui-tabs-vertical .ui-tabs-nav li { clear: left; width: 100%; border-bottom-width: 1px !important; border-right-width: 0 !important; margin: 0 -1px .2em 0; }
.ui-tabs-vertical .ui-tabs-nav li a { display:block; }
.ui-tabs-vertical .ui-tabs-nav li.ui-tabs-active { padding-bottom: 0; padding-right: .1em; border-right-width: 1px; border-right-width: 1px; }
.ui-tabs-vertical .ui-tabs-panel { padding: 1em; float: right; width: 40em;}
.markrow { background-color:#ffbba9 !important; }
</style>
</head>
<body>
@ -375,4 +385,4 @@ hr{margin:18px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff
</div>
<div id="info_panels"></div>
</body>
</html>
</html>

View File

@ -22,6 +22,8 @@
#include <cstring>
#include <cstdio>
#define TO_UPPER(S) transform(S.begin(),S.end(),S.begin(),(int(*)(int))toupper)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -473,6 +475,37 @@ bool Template::get(
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
bool Template::get(
const string& name,
bool& value) const
{
string sval;
get(name, sval);
if ( sval == "" )
{
value = false;
return false;
}
TO_UPPER(sval);
if ( sval == "YES" )
{
value = true;
}
else
{
value = false;
}
return true;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string& Template::to_xml(string& xml) const
{
multimap<string,Attribute *>::const_iterator it;

View File

@ -81,14 +81,10 @@ CLONE_CMD=$(cat <<EOF
$SUDO $LVCREATE -L\${SIZE} ${VG_NAME} -n ${TARGET_LV_NAME}
# clone lv with dd
$SUDO $DD if=$SOURCE_DEV of=$TARGET_DEV bs=64k
$SUDO $DD if=$SOURCE_DEV of=$TARGET_DEV bs=2M
# new iscsi target
TID=\$($SUDO $(tgtadm_next_tid))
$SUDO $(tgtadm_target_new "\$TID" "$NEW_IQN")
$SUDO $(tgtadm_target_bind_all "\$TID")
$SUDO $(tgtadm_logicalunit_new "\$TID" "$TARGET_DEV")
$SUDO $(tgt_setup_lun "$NEW_IQN" "$TARGET_DEV")
$SUDO $(tgt_admin_dump_config "$TARGET_CONF")
EOF
)
@ -96,18 +92,27 @@ EOF
ssh_exec_and_log "$TARGET_HOST" "$CLONE_CMD" \
"Error cloning $DST_HOST:$TARGET_DEV"
DISCOVERY_CMD=$(cat <<EOF
LINK_CMD=$(cat <<EOF
set -e
# discover and login
mkdir -p $DST_DIR
$SUDO $(iscsiadm_discovery "$TARGET_HOST")
$SUDO $(iscsiadm_login "$NEW_IQN" "$TARGET_HOST")
sleep 2
# poll
while [ ! -L /dev/disk/by-path/*$NEW_IQN-lun-1 ]; do
sleep 1
done
# link
DISK_BY_PATH=\$(ls /dev/disk/by-path/*$NEW_IQN-lun-1)
ln -s "\$DISK_BY_PATH" "$DST_PATH"
DISK_DEVNAME=\$(readlink -f \$DISK_BY_PATH | awk -F'/' '{ print \$NF }')
EOF
)
ssh_exec_and_log "$DST_HOST" "$DISCOVERY_CMD" \
"Error discovering $NEW_IQN in $DST_HOST"
ssh_exec_and_log "$DST_HOST" "$LINK_CMD" \
"Error linking $NEW_IQN in $DST_HOST"
exit 0

View File

@ -58,18 +58,26 @@ VG_NAME=`echo $TARGET|$AWK -F. '{print $(NF-1)}'`
TARGET_DEV="/dev/$VG_NAME/$LV_NAME"
TARGET_HOST=${TARGET%.$VG_NAME.$LV_NAME}
DISCOVER_CMD=$(cat <<EOF
LINK_CMD=$(cat <<EOF
set -e
# discover and login
mkdir -p $DST_DIR
$SUDO $(iscsiadm_discovery "$TARGET_HOST")
$SUDO $(iscsiadm_login "$IQN" "$TARGET_HOST")
sleep 2
# poll
while [ ! -L /dev/disk/by-path/*$IQN-lun-1 ]; do
sleep 1
done
# link
DISK_BY_PATH=\$(ls /dev/disk/by-path/*$IQN-lun-1)
ln -s "\$DISK_BY_PATH" "$DST_PATH"
EOF
)
ssh_exec_and_log "$DST_HOST" "$DISCOVER_CMD" \
"Error registering $DST_HOST:$DEV"
ssh_exec_and_log "$DST_HOST" "$LINK_CMD" \
"Error linking $DST_HOST:$TARGET_DEV"
exit 0

View File

@ -114,19 +114,29 @@ if is_iscsi "$DST_HOST"; then
TARGET_HOST=$(iqn_get_host "$IQN")
LOGIN_CMD=$(cat <<EOF
set -e
mkdir -p $DST_DIR
$SUDO $(iscsiadm_discovery "$TARGET_HOST")
$SUDO $(iscsiadm_login "$IQN" "$TARGET_HOST")
LINK_CMD=$(cat <<EOF
set -e
# discover and login
mkdir -p $DST_DIR
$SUDO $(iscsiadm_discovery "$TARGET_HOST")
$SUDO $(iscsiadm_login "$IQN" "$TARGET_HOST")
# poll
while [ ! -L /dev/disk/by-path/*$IQN-lun-1 ]; do
sleep 1
DISK_BY_PATH=\$(ls /dev/disk/by-path/*$IQN-lun-1)
ln -sf "\$DISK_BY_PATH" "$DST_PATH"
done
# link
DISK_BY_PATH=\$(ls /dev/disk/by-path/*$IQN-lun-1)
ln -sf "\$DISK_BY_PATH" "$DST_PATH"
EOF
)
ssh_exec_and_log "$DST_HOST" "$LOGIN_CMD" \
"Error logging in $IQN"
ssh_exec_and_log "$DST_HOST" "$LINK_CMD" \
"Error linking to $DISK_BY_PATH $DST_PATH"
fi
exit 0

View File

@ -101,7 +101,7 @@ CLONE_CMD=$(cat <<EOF
set -e
# clone lv with dd
$SUDO $DD if=$SOURCE_DEV of=$TARGET_DEV bs=64k
$SUDO $DD if=$SOURCE_DEV of=$TARGET_DEV bs=2M
# remove if source_dev is not persistent
if [ -z "$PERSISTENT" ]; then

View File

@ -15,6 +15,7 @@
/* -------------------------------------------------------------------------- */
#include "Quota.h"
#include <math.h>
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -63,7 +64,6 @@ int Quota::get_quota(
void Quota::add_to_quota(VectorAttribute * attr, const string& va_name, float num)
{
istringstream iss;
ostringstream oss;
float total;
iss.str(attr->vector_value(va_name.c_str()));
@ -72,9 +72,7 @@ void Quota::add_to_quota(VectorAttribute * attr, const string& va_name, float nu
total += num;
oss << total;
attr->replace(va_name, oss.str());
attr->replace(va_name, float_to_str(total));
}
/* -------------------------------------------------------------------------- */
@ -371,24 +369,22 @@ int Quota::update_limits(
VectorAttribute * quota,
const VectorAttribute * va)
{
string limit;
float limit_i;
string limit;
float limit_f;
for (int i=0; i < num_metrics; i++)
{
limit = va->vector_value_str(metrics[i], limit_i);
limit = va->vector_value_str(metrics[i], limit_f);
//No quota, NaN or negative
if ((!is_default &&
( limit_i < -1 || ( limit_i == -1 && limit == "" ))) ||
(is_default && limit_i < 0) )
( limit_f < -1 || ( limit_f == -1 && limit == "" ))) ||
(is_default && limit_f < 0) )
{
return -1;
}
else
{
quota->replace(metrics[i], limit);
}
quota->replace(metrics[i], float_to_str(limit_f));
}
return 0;
@ -402,7 +398,7 @@ VectorAttribute * Quota::new_quota(VectorAttribute * va)
map<string,string> limits;
string limit;
int limit_i;
float limit_f;
for (int i=0; i < num_metrics; i++)
{
@ -410,16 +406,16 @@ VectorAttribute * Quota::new_quota(VectorAttribute * va)
metrics_used += "_USED";
limit = va->vector_value_str(metrics[i], limit_i);
limit = va->vector_value_str(metrics[i], limit_f);
//No quota, NaN or negative
if ( (!is_default && limit_i < -1) ||
(is_default && limit_i < 0) )
if ( (!is_default && limit_f < -1) ||
(is_default && limit_f < 0) )
{
return 0;
}
limits.insert(make_pair(metrics[i], limit));
limits.insert(make_pair(metrics[i], float_to_str(limit_f)));
limits.insert(make_pair(metrics_used, "0"));
}
@ -433,3 +429,23 @@ VectorAttribute * Quota::new_quota(VectorAttribute * va)
return new VectorAttribute(template_name,limits);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string Quota::float_to_str(const float &num)
{
ostringstream oss;
if ( num == ceil(num) )
{
oss.precision(0);
}
else
{
oss.precision(2);
}
oss << fixed << num;
return oss.str();
}

View File

@ -25,6 +25,7 @@
/* -------------------------------------------------------------------------- */
time_t VirtualMachinePool::_monitor_expiration;
bool VirtualMachinePool::_submit_on_hold;
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -35,7 +36,8 @@ VirtualMachinePool::VirtualMachinePool(
const string& hook_location,
const string& remotes_location,
vector<const Attribute *>& restricted_attrs,
time_t expire_time)
time_t expire_time,
bool on_hold)
: PoolSQL(db, VirtualMachine::table, false)
{
const VectorAttribute * vattr;
@ -50,6 +52,7 @@ VirtualMachinePool::VirtualMachinePool(
bool state_hook = false;
_monitor_expiration = expire_time;
_submit_on_hold = on_hold;
if ( _monitor_expiration == 0 )
{
@ -232,7 +235,7 @@ int VirtualMachinePool::allocate (
// ------------------------------------------------------------------------
vm = new VirtualMachine(-1, uid, gid, uname, gname, vm_template);
if (on_hold == true)
if ( _submit_on_hold == true || on_hold )
{
vm->state = VirtualMachine::HOLD;
}