diff --git a/include/RequestManagerAllocate.h b/include/RequestManagerAllocate.h
index 8b3497b418..faceccd4db 100644
--- a/include/RequestManagerAllocate.h
+++ b/include/RequestManagerAllocate.h
@@ -205,6 +205,10 @@ public:
 
     void request_execute(xmlrpc_c::paramList const& _paramList,
                          RequestAttributes& att);
+
+    bool allocate_authorization(Template *          obj_template,
+                                RequestAttributes&  att,
+                                PoolObjectAuth *    cluster_perms);
 };
 
 /* ------------------------------------------------------------------------- */
diff --git a/src/image/Image.cc b/src/image/Image.cc
index dfa867ee24..e05c4b8ffd 100644
--- a/src/image/Image.cc
+++ b/src/image/Image.cc
@@ -95,25 +95,10 @@ int Image::insert(SqlDB *db, string& error_str)
     string persistent_attr;
     string dev_prefix;
     string source_attr;
-    string aname;
     string saved_id;
 
     ostringstream oss;
 
-    // ------------------------------------------------------------------------
-    // Check template for restricted attributes
-    // ------------------------------------------------------------------------
-
-    if ( uid != 0 && gid != GroupPool::ONEADMIN_ID )
-    {
-        ImageTemplate *img_template = static_cast<ImageTemplate *>(obj_template);
-
-        if (img_template->check(aname))
-        {
-            goto error_restricted;
-        }
-    }
-
     // ---------------------------------------------------------------------
     // Check default image attributes
     // ---------------------------------------------------------------------
@@ -242,11 +227,6 @@ error_path_and_source:
     error_str = "Template malformed, PATH and SOURCE are mutually exclusive.";
     goto error_common;
 
-error_restricted:
-    oss << "Template includes a restricted attribute " << aname << ".";
-    error_str = oss.str();
-    goto error_common;
-
 error_common:
     NebulaLog::log("IMG", Log::ERROR, error_str);
     return -1;
diff --git a/src/mad/sh/scripts_common.sh b/src/mad/sh/scripts_common.sh
index 1296f3c65a..204b87eb38 100755
--- a/src/mad/sh/scripts_common.sh
+++ b/src/mad/sh/scripts_common.sh
@@ -27,6 +27,7 @@ ISCSIADM=iscsiadm
 LVCREATE=lvcreate
 LVREMOVE=lvremove
 LVS=lvs
+LN=ln
 MD5SUM=md5sum
 MKFS=mkfs
 MKISOFS=mkisofs
@@ -211,7 +212,7 @@ function mkfs_command {
 #This function executes $2 at $1 host and report error $3
 function ssh_exec_and_log
 {
-    SSH_EXEC_ERR=`$SSH $1 bash -s 2>&1 1>/dev/null <<EOF
+    SSH_EXEC_ERR=`$SSH $1 sh -s 2>&1 1>/dev/null <<EOF
 $2
 EOF`
     SSH_EXEC_RC=$?
@@ -232,7 +233,7 @@ EOF`
 #Creates path ($2) at $1
 function ssh_make_path
 {
-    SSH_EXEC_ERR=`$SSH $1 bash -s 2>&1 1>/dev/null <<EOF
+    SSH_EXEC_ERR=`$SSH $1 sh -s 2>&1 1>/dev/null <<EOF
 if [ ! -d $2 ]; then
    mkdir -p $2
 fi
diff --git a/src/rm/RequestManagerAllocate.cc b/src/rm/RequestManagerAllocate.cc
index 5342d9efd8..e5c70bda4a 100644
--- a/src/rm/RequestManagerAllocate.cc
+++ b/src/rm/RequestManagerAllocate.cc
@@ -76,9 +76,28 @@ bool VirtualMachineAllocate::allocate_authorization(
 
     AuthRequest ar(att.uid, att.gid);
     string      t64;
+    string      aname;
 
     VirtualMachineTemplate * ttmpl = static_cast<VirtualMachineTemplate *>(tmpl);
 
+    // Check template for restricted attributes
+
+    if ( att.uid != 0 && att.gid != GroupPool::ONEADMIN_ID )
+    {
+        if (ttmpl->check(aname))
+        {
+            ostringstream oss;
+
+            oss << "VM Template includes a restricted attribute " << aname;
+
+            failure_response(AUTHORIZATION,
+                    authorization_error(oss.str(), att),
+                    att);
+
+            return false;
+        }
+    }
+
     ar.add_create_auth(auth_object, tmpl->to_xml(t64));
 
     VirtualMachine::set_auth_request(att.uid, ar, ttmpl);
@@ -98,6 +117,39 @@ bool VirtualMachineAllocate::allocate_authorization(
 /* -------------------------------------------------------------------------- */
 /* -------------------------------------------------------------------------- */
 
+bool ImageAllocate::allocate_authorization(
+        Template *          tmpl,
+        RequestAttributes&  att,
+        PoolObjectAuth *    cluster_perms)
+{
+    string      aname;
+
+    ImageTemplate * itmpl = static_cast<ImageTemplate *>(tmpl);
+
+    // Check template for restricted attributes
+
+    if ( att.uid != 0 && att.gid != GroupPool::ONEADMIN_ID )
+    {
+        if (itmpl->check(aname))
+        {
+            ostringstream oss;
+
+            oss << "Template includes a restricted attribute " << aname;
+
+            failure_response(AUTHORIZATION,
+                    authorization_error(oss.str(), att),
+                    att);
+
+            return false;
+        }
+    }
+
+    return RequestManagerAllocate::allocate_authorization(tmpl, att, cluster_perms);
+}
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
 void RequestManagerAllocate::request_execute(xmlrpc_c::paramList const& params,
                                              RequestAttributes& att)
 {
diff --git a/src/rm/RequestManagerVMTemplate.cc b/src/rm/RequestManagerVMTemplate.cc
index a62aa2f56d..d354d5a037 100644
--- a/src/rm/RequestManagerVMTemplate.cc
+++ b/src/rm/RequestManagerVMTemplate.cc
@@ -39,6 +39,7 @@ void VMTemplateInstantiate::request_execute(xmlrpc_c::paramList const& paramList
     VMTemplate *             rtmpl;
 
     string error_str;
+    string aname;
 
     rtmpl = tpool->get(id,true);
 
@@ -57,6 +58,26 @@ void VMTemplateInstantiate::request_execute(xmlrpc_c::paramList const& paramList
 
     rtmpl->unlock();
 
+    // Check template for restricted attributes, but only if the Template owner
+    // is not oneadmin
+
+    if ( perms.uid != 0 && perms.gid != GroupPool::ONEADMIN_ID )
+    {
+        if (tmpl->check(aname))
+        {
+            ostringstream oss;
+
+            oss << "VM Template includes a restricted attribute " << aname;
+
+            failure_response(AUTHORIZATION,
+                    authorization_error(oss.str(), att),
+                    att);
+
+            delete tmpl;
+            return;
+        }
+    }
+
     tmpl->erase("NAME");
     tmpl->set(new SingleAttribute("NAME",name));
 
diff --git a/src/tm_mad/common/context b/src/tm_mad/common/context
index a36c2e5699..d519110140 100755
--- a/src/tm_mad/common/context
+++ b/src/tm_mad/common/context
@@ -73,6 +73,9 @@ exec_and_log "$MKISOFS -o $ISO_FILE -J -R $ISO_DIR" "Error creating iso fs"
 
 exec_and_log "$SCP $ISO_FILE $DST" "Error copying context ISO to $DST"
 
+# Creates symbolic link to add a .iso suffix, needed for VMware CDROMs
+ssh_exec_and_log $DST_HOST "$LN -s $DST_PATH $DST_PATH.iso" "Error creating ISO symbolic link"
+
 rm -rf $ISO_DIR > /dev/null 2>&1
 
 exit 0
diff --git a/src/tm_mad/shared/ln b/src/tm_mad/shared/ln
index 4ecb76e42b..2a9395d484 100755
--- a/src/tm_mad/shared/ln
+++ b/src/tm_mad/shared/ln
@@ -16,7 +16,7 @@
 # limitations under the License.                                             #
 #--------------------------------------------------------------------------- #
 
-# ln fe:SOURCE host:remote_system_ds/disk.i size
+# ln fe:SOURCE host:remote_system_ds/disk.i
 #   - fe is the front-end hostname
 #   - SOURCE is the path of the disk image in the form DS_BASE_PATH/disk
 #   - host is the target host to deploy the VM
@@ -43,16 +43,41 @@ DST_PATH=`arg_path $DST`
 DST_HOST=`arg_host $DST`
 DST_DIR=`dirname $DST_PATH`
 
-ssh_make_path $DST_HOST $DST_DIR
-
 #-------------------------------------------------------------------------------
 # Link (ln) SRC into DST
 #-------------------------------------------------------------------------------
 
-log "Linking $SRC_PATH in $DST"
+# Is it a file or a folder (VMware)?
+if [ -d `arg_path $SRC`  ]; then
+	ssh_make_path $DST_HOST $DST_PATH
+
+	# It's a folder, make links for all elements
+    SRC_FOLDER_NAME=`basename $SRC_PATH`
+    SRC_WITH_NO_FOLDER=`dirname $SRC_PATH`
+    SRC_DS_NAME=`basename $SRC_WITH_NO_FOLDER`
+	REL_SRC_PATH="../../../$SRC_DS_NAME/$SRC_FOLDER_NAME"
+
+	log "Link all files in $SRC_PATH to $DST_PATH"
+
+LINK_SCRIPT=$(cat <<EOF
+for file in \$(cd $DST_DIR  ; find $SRC_PATH -type f); do
+	FNAME=\$(basename \$file)
+	(cd $DST_PATH ;  ln -sf $REL_SRC_PATH/\$FNAME $DST_PATH/$FNAME)
+done
+EOF
+)
+	ssh_exec_and_log $DST_HOST "$LINK_SCRIPT" "Could not link dir files from source DS to system DS"
+else
+	ssh_make_path $DST_HOST $DST_DIR
+
+	# Just link a file
+	log "Linking $SRC_PATH in $DST"
+
+	ssh_exec_and_log $DST_HOST \
+				     "cd $DST_DIR; ln -s $SRC_PATH $DST_PATH" \
+	             	 "Error linking $SRC to $DST"
+fi
 
-ssh_exec_and_log $DST_HOST \
-			     "cd $DST_DIR; ln -s $SRC_PATH $DST_PATH" \
-             	 "Error linking $SRC to $DST"
 
 exit 0
+
diff --git a/src/tm_mad/ssh/clone b/src/tm_mad/ssh/clone
index 87a95357fb..8a81d9b95d 100755
--- a/src/tm_mad/ssh/clone
+++ b/src/tm_mad/ssh/clone
@@ -58,6 +58,6 @@ http://*)
 
 *)
     log "Cloning $SRC in $DST_PATH"
-    exec_and_log "$SCP $SRC $DST" "Error copying $SRC to $DST"
+    exec_and_log "$SCP -r $SRC $DST" "Error copying $SRC to $DST"
     ;;
 esac
diff --git a/src/tm_mad/ssh/mvds b/src/tm_mad/ssh/mvds
index 74bb8cc8cf..47c66b6b41 100755
--- a/src/tm_mad/ssh/mvds
+++ b/src/tm_mad/ssh/mvds
@@ -49,6 +49,6 @@ SRC_HOST=`arg_host $SRC`
 # Move the image back to the datastore
 #-------------------------------------------------------------------------------
 log "Moving $SRC_PATH to datastore as $DST_PATH"
-exec_and_log "$SCP $SRC $DST" "Error copying $SRC to $DST"
+exec_and_log "$SCP -r $SRC $DST" "Error copying $SRC to $DST"
 
 exit 0
diff --git a/src/tm_mad/tm_common.sh b/src/tm_mad/tm_common.sh
index a604f6cf05..4aeeb7ad84 100644
--- a/src/tm_mad/tm_common.sh
+++ b/src/tm_mad/tm_common.sh
@@ -70,3 +70,18 @@ function is_disk
         echo "0"
     fi
 }
+
+#Makes path src ($1) relative to dst ($2)
+function make_relative {
+    src=$1
+    dst=$2
+
+    common=$dst
+
+    while [ -z "`echo $src | grep -E "^$common"`" ]; do
+        common=`dirname $common`
+        dots="../$dots"
+    done
+
+    echo $dots${src#$common/}
+}
diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc
index 38fd4100f0..f11f91ac70 100644
--- a/src/vm/VirtualMachine.cc
+++ b/src/vm/VirtualMachine.cc
@@ -198,26 +198,9 @@ int VirtualMachine::insert(SqlDB * db, string& error_str)
     int    rc;
     string name;
 
-    SingleAttribute * attr;
-    string aname;
-    string value;
-
-    ostringstream     oss;
-
-    // ------------------------------------------------------------------------
-    // Check template for restricted attributes
-    // ------------------------------------------------------------------------
-
-    if ( uid != 0 && gid != GroupPool::ONEADMIN_ID )
-    {
-        VirtualMachineTemplate *vt = 
-            static_cast<VirtualMachineTemplate *>(obj_template);
-        
-        if (vt->check(aname))
-        {
-            goto error_restricted;            
-        }
-    }
+    SingleAttribute *   attr;
+    string              value;
+    ostringstream       oss;
 
     // ------------------------------------------------------------------------
     // Set a name if the VM has not got one and VM_ID
@@ -327,11 +310,6 @@ error_leases_rollback:
     release_network_leases();
     goto error_common;
 
-error_restricted:
-    oss << "VM Template includes a restricted attribute " << aname << "."; 
-    error_str = oss.str(); 
-    goto error_common;
-
 error_name_length:
     oss << "NAME is too long; max length is 128 chars.";
     error_str = oss.str(); 
diff --git a/src/vmm/LibVirtDriverVMware.cc b/src/vmm/LibVirtDriverVMware.cc
index 856ef5131f..076c864ed8 100644
--- a/src/vmm/LibVirtDriverVMware.cc
+++ b/src/vmm/LibVirtDriverVMware.cc
@@ -222,19 +222,19 @@ int LibVirtDriver::deployment_description_vmware(
         {
             file << "\t\t<disk type='block' device='disk'>" << endl;
             file << "\t\t\t<source file=[" <<  datastore << "] " << vm->get_oid()
-                << "/images/disk."  << i << "'/>"  << endl;
+                << "/disk."  << i << "'/>"  << endl;
         }
         else if ( type == "CDROM" )
         {
             file << "\t\t<disk type='file' device='cdrom'>" << endl;
             file << "\t\t\t<source file=[" <<  datastore << "] " << vm->get_oid()
-                << "/images/disk."  << i << ".iso'/>"  << endl;
+                << "/disk."  << i << ".iso'/>"  << endl;
         }
         else
         {
             file << "\t\t<disk type='file' device='disk'>" << endl
                  << "\t\t\t<source file='[" <<  datastore <<"] " << vm->get_oid()
-                 << "/images/disk." << i << "/disk.vmdk'/>" << endl;
+                 << "/disk." << i << "/disk.vmdk'/>" << endl;
         }
 
         file << "\t\t\t<target dev='" << target << "'";
diff --git a/src/vmm_mad/exec/vmm_exec_vmware.conf b/src/vmm_mad/exec/vmm_exec_vmware.conf
index 3075ff7625..75f9556ff9 100644
--- a/src/vmm_mad/exec/vmm_exec_vmware.conf
+++ b/src/vmm_mad/exec/vmm_exec_vmware.conf
@@ -28,8 +28,9 @@ MEMORY = 256
 OS     = [ ARCH = i686 ]
 DISK   = [ DRIVER = file ]
 
-# Name of the datastore in the remote VMware hypervisors
-# mounting $ONE_LOCATION/var exported as a nfs share
-# by the OpenNebula front-end
+# Name of the system datastore in the remote VMware hypervisors
+# mounting DATASTORE_LOCATION/var/datastore/0 exported as a nfs share
+# by the OpenNebula front-end. This would need to be changed
+# *only* with custom TM drivers
 
-DATASTORE = images
+DATASTORE = 0
diff --git a/src/vmm_mad/remotes/vmware/vmware_driver.rb b/src/vmm_mad/remotes/vmware/vmware_driver.rb
index c5be771f11..9ce7c9abd7 100644
--- a/src/vmm_mad/remotes/vmware/vmware_driver.rb
+++ b/src/vmm_mad/remotes/vmware/vmware_driver.rb
@@ -165,7 +165,8 @@ class VMwareDriver
     def restore(checkpoint)
         begin
             # Define the VM
-            dfile = File.dirname(File.dirname(checkpoint)) + "/deployment.0"
+            dfile = VAR_LOCATION + "/" + 
+                    File.basename(File.dirname(checkpoint)) + "/deployment.0"
         rescue => e
             OpenNebula.log_error("Cannot open checkpoint #{e.message}")
             exit -1