From a4460bea2bbd727f3266a7e4b8a5085b5b54b158 Mon Sep 17 00:00:00 2001
From: juanmont <jjmontiel@opennebula.org>
Date: Tue, 23 Jan 2018 12:57:24 +0100
Subject: [PATCH 1/6] B #1412: Prevented attach action with images in LOCKED
 state

---
 include/ImageManager.h           |  9 ++++++---
 include/ImagePool.h              |  3 ++-
 src/image/ImageManagerActions.cc | 31 ++++++++++++++++++++++++++-----
 src/image/ImagePool.cc           |  7 ++++---
 src/vm/VirtualMachineDisk.cc     |  4 ++--
 5 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/include/ImageManager.h b/include/ImageManager.h
index a155758775..6548eb28a1 100644
--- a/include/ImageManager.h
+++ b/include/ImageManager.h
@@ -94,18 +94,20 @@ public:
      *  Try to acquire an image from the repository for a VM.
      *    @param image_id id of image
      *    @param error string describing the error
+     *    @param attach indicates that are trying to make an attachment of the image
      *    @return pointer to the image or 0 if could not be acquired
      */
-    Image * acquire_image(int vm_id, int image_id, string& error);
+    Image * acquire_image(int vm_id, int image_id, string& error, bool attach);
 
     /**
      *  Try to acquire an image from the repository for a VM.
      *    @param name of the image
      *    @param id of owner
      *    @param error string describing the error
+     *    @param attach indicates that are trying to make an attachment of the image
      *    @return pointer to the image or 0 if could not be acquired
      */
-    Image * acquire_image(int vm_id, const string& name, int uid, string& error);
+    Image * acquire_image(int vm_id, const string& name, int uid, string& error, bool attach);
 
     /**
      *  Releases an image and triggers any needed operations in the repo
@@ -358,9 +360,10 @@ private:
     /**
      *  Acquires an image updating its state.
      *    @param image pointer to image, it should be locked
+     *    @param attach indicates that are trying to make an attachment of the image
      *    @return 0 on success
      */
-    int acquire_image(int vm_id, Image *img, string& error);
+    int acquire_image(int vm_id, Image *img, string& error, bool attach);
 
     /**
      *  Moves a file to an image in the repository
diff --git a/include/ImagePool.h b/include/ImagePool.h
index a5fb6a37dd..d38faa8e3a 100644
--- a/include/ImagePool.h
+++ b/include/ImagePool.h
@@ -166,7 +166,8 @@ public:
                      int                uid,
                      int&               image_id,
                      Snapshots **       snaps,
-                     string&            error_str);
+                     string&            error_str,
+                     bool               attach);
     /**
      *  Generates a DISK attribute for VM templates using the Image metadata
      *
diff --git a/src/image/ImageManagerActions.cc b/src/image/ImageManagerActions.cc
index a1071caf12..d4703507d7 100644
--- a/src/image/ImageManagerActions.cc
+++ b/src/image/ImageManagerActions.cc
@@ -25,7 +25,7 @@
 /* -------------------------------------------------------------------------- */
 /* -------------------------------------------------------------------------- */
 
-Image * ImageManager::acquire_image(int vm_id, int image_id, string& error)
+Image * ImageManager::acquire_image(int vm_id, int image_id, string& error, bool attach)
 {
     Image * img;
     int     rc;
@@ -41,7 +41,7 @@ Image * ImageManager::acquire_image(int vm_id, int image_id, string& error)
         return 0;
     }
 
-    rc = acquire_image(vm_id, img, error);
+    rc = acquire_image(vm_id, img, error, attach);
 
     if ( rc != 0 )
     {
@@ -54,7 +54,7 @@ Image * ImageManager::acquire_image(int vm_id, int image_id, string& error)
 
 /* -------------------------------------------------------------------------- */
 
-Image * ImageManager::acquire_image(int vm_id, const string& name, int uid, string& error)
+Image * ImageManager::acquire_image(int vm_id, const string& name, int uid, string& error, bool attach)
 {
     Image * img;
     int     rc;
@@ -71,7 +71,7 @@ Image * ImageManager::acquire_image(int vm_id, const string& name, int uid, stri
         return 0;
     }
 
-    rc = acquire_image(vm_id, img, error);
+    rc = acquire_image(vm_id, img, error, attach);
 
     if ( rc != 0 )
     {
@@ -84,7 +84,7 @@ Image * ImageManager::acquire_image(int vm_id, const string& name, int uid, stri
 
 /* -------------------------------------------------------------------------- */
 
-int ImageManager::acquire_image(int vm_id, Image *img, string& error)
+int ImageManager::acquire_image(int vm_id, Image *img, string& error, bool attach)
 {
     int rc = 0;
 
@@ -126,6 +126,15 @@ int ImageManager::acquire_image(int vm_id, Image *img, string& error)
         break;
 
         case Image::LOCKED:
+            if (attach)
+            {
+                oss << "Cannot acquire image " << img->get_oid()
+                << ", it is locked";
+
+                error = oss.str();
+                rc    = -1;
+            }
+
             img->inc_running(vm_id);
 
             if ( img->is_persistent() )
@@ -150,7 +159,19 @@ int ImageManager::acquire_image(int vm_id, Image *img, string& error)
         break;
 
         case Image::USED:
+            img->inc_running(vm_id);
+            ipool->update(img);
+        break;
         case Image::LOCKED_USED:
+            if (attach)
+            {
+                oss << "Cannot acquire image " << img->get_oid()
+                << ", it is locked";
+
+                error = oss.str();
+                rc    = -1;
+            }
+
             img->inc_running(vm_id);
             ipool->update(img);
         break;
diff --git a/src/image/ImagePool.cc b/src/image/ImagePool.cc
index c31490c85f..85f5145e94 100644
--- a/src/image/ImagePool.cc
+++ b/src/image/ImagePool.cc
@@ -297,7 +297,8 @@ int ImagePool::acquire_disk(int               vm_id,
                             int               uid,
                             int&              image_id,
                             Snapshots **      snap,
-                            string&           error_str)
+                            string&           error_str,
+                            bool              attach)
 {
     string  source;
     Image * img = 0;
@@ -314,7 +315,7 @@ int ImagePool::acquire_disk(int               vm_id,
 
     if ( disk->vector_value("IMAGE_ID", iid) == 0 )
     {
-        img = imagem->acquire_image(vm_id, iid, error_str);
+        img = imagem->acquire_image(vm_id, iid, error_str, attach);
 
         if ( img == 0 )
         {
@@ -336,7 +337,7 @@ int ImagePool::acquire_disk(int               vm_id,
             return -1;
         }
 
-        img = imagem->acquire_image(vm_id, source, uiid, error_str);
+        img = imagem->acquire_image(vm_id, source, uiid, error_str, attach);
 
         if ( img == 0 )
         {
diff --git a/src/vm/VirtualMachineDisk.cc b/src/vm/VirtualMachineDisk.cc
index b51b38c3f9..53951c6afb 100644
--- a/src/vm/VirtualMachineDisk.cc
+++ b/src/vm/VirtualMachineDisk.cc
@@ -751,7 +751,7 @@ int VirtualMachineDisks::get_images(int vm_id, int uid, const std::string& tsys,
         }
 
         if ( ipool->acquire_disk(vm_id, disk, disk_id, image_type, dev_prefix,
-                uid, image_id, &snapshots, error_str) != 0 )
+                uid, image_id, &snapshots, error_str, false) != 0 )
         {
             oss << "DISK " << disk_id << ": " << error_str;
             error_str = oss.str();
@@ -1076,7 +1076,7 @@ VirtualMachineDisk * VirtualMachineDisks::set_up_attach(int vmid, int uid,
     VirtualMachineDisk * disk = new VirtualMachineDisk(vdisk, max_disk_id + 1);
 
     int rc = ipool->acquire_disk(vmid, disk, max_disk_id + 1, img_type,
-                         dev_prefix, uid, image_id, &snap, error);
+                         dev_prefix, uid, image_id, &snap, error, true);
     if ( rc != 0 )
     {
         return 0;

From 113200229a9b55c29c316008eb5e8772e68bca70 Mon Sep 17 00:00:00 2001
From: Vlastimil Holer <vlastimil.holer@gmail.com>
Date: Tue, 23 Jan 2018 15:43:43 +0100
Subject: [PATCH 2/6] B #1222: Avoid using rbd map in tm_mad Ceph

---
 src/mad/sh/scripts_common.sh |  2 +-
 src/tm_mad/ceph/mkimage      | 27 +++++++++++++++++++++++----
 src/tm_mad/ceph/mvds         | 11 ++++++++---
 3 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/src/mad/sh/scripts_common.sh b/src/mad/sh/scripts_common.sh
index 5ec094f37a..7333493b72 100644
--- a/src/mad/sh/scripts_common.sh
+++ b/src/mad/sh/scripts_common.sh
@@ -38,7 +38,7 @@ MD5SUM=${MD5SUM:-md5sum}
 MKFS=${MKFS:-mkfs}
 MKISOFS=${MKISOFS:-genisoimage}
 MKSWAP=${MKSWAP:-mkswap}
-QEMU_IMG=${QMEMU_IMG:-qemu-img}
+QEMU_IMG=${QEMU_IMG:-qemu-img}
 RADOS=${RADOS:-rados}
 RBD=${RBD:-rbd}
 READLINK=${READLINK:-readlink}
diff --git a/src/tm_mad/ceph/mkimage b/src/tm_mad/ceph/mkimage
index a24b7c159a..8d87eba7e4 100755
--- a/src/tm_mad/ceph/mkimage
+++ b/src/tm_mad/ceph/mkimage
@@ -83,16 +83,21 @@ CEPH_CONF="${XPATH_ELEMENTS[j++]}"
 POOL_NAME="${XPATH_ELEMENTS[j++]:-$POOL_NAME}"
 RBD_FORMAT="${XPATH_ELEMENTS[j++]:-$RBD_FORMAT}"
 
+QEMU_OPTS=''
+
 if [ -n "$CEPH_USER" ]; then
     RBD="$RBD --id ${CEPH_USER}"
+    QEMU_OPTS="${QEMU_OPTS}:id=${CEPH_USER}"
 fi
 
 if [ -n "$CEPH_KEY" ]; then
     RBD="$RBD --keyfile ${CEPH_KEY}"
+    QEMU_OPTS="${QEMU_OPTS}:keyfile=${CEPH_KEY}"
 fi
 
 if [ -n "$CEPH_CONF" ]; then
     RBD="$RBD --conf ${CEPH_CONF}"
+    QEMU_OPTS="${QEMU_OPTS}:conf=${CEPH_CONF}"
 fi
 
 if [ "$RBD_FORMAT" = "2" ]; then
@@ -101,14 +106,27 @@ fi
 
 RBD_SOURCE="${POOL_NAME}/one-sys-${VMID}-${DISK_ID}"
 
+ssh_make_path $DST_HOST $DST_DIR
+
+# if user requested a swap, we need to create a local
+# swap formatted image and upload into existing Ceph image
+MKFS_CMD=`mkfs_command $DST_PATH $FSTYPE $SIZE`
+
 MKIMAGE_CMD=$(cat <<EOF
+    set -e -o pipefail
+
     export PATH=/usr/sbin:/sbin:\$PATH
-    $RBD create $FORMAT_OPT $RBD_SOURCE --size ${SIZE} || exit \$?
+
+    $RBD create $FORMAT_OPT $RBD_SOURCE --size ${SIZE}
 
     if [ "$FSTYPE" = "swap" ]; then
-        $SUDO $RBD map $RBD_SOURCE || exit \$?
-        $SUDO $MKSWAP -L swap /dev/rbd/$RBD_SOURCE
-        $SUDO $RBD unmap /dev/rbd/$RBD_SOURCE
+        ${MKFS_CMD}
+
+        ${QEMU_IMG} convert -n \
+            -f raw "${DST_PATH}" \
+            -O rbd "rbd:${RBD_SOURCE}${QEMU_OPTS}"
+
+        ${RM} -f "${DST_PATH}"
     fi
 EOF
 )
@@ -116,6 +134,7 @@ EOF
 DELIMAGE_CMD=$(cat <<EOF
     export PATH=/usr/sbin:/sbin:\$PATH
     $RBD rm $RBD_SOURCE
+    ${RM} -f "${DST_PATH}"
 EOF
 )
 
diff --git a/src/tm_mad/ceph/mvds b/src/tm_mad/ceph/mvds
index a2dbfb3f29..c3600ea474 100755
--- a/src/tm_mad/ceph/mvds
+++ b/src/tm_mad/ceph/mvds
@@ -89,16 +89,21 @@ ORIGINAL_SIZE="${XPATH_ELEMENTS[j++]}"
 # Copy Image back to the datastore
 #-------------------------------------------------------------------------------
 
+QEMU_OPTS=''
+
 if [ -n "$CEPH_USER" ]; then
     RBD="$RBD --id ${CEPH_USER}"
+    QEMU_OPTS="${QEMU_OPTS}:id=${CEPH_USER}"
 fi
 
 if [ -n "$CEPH_KEY" ]; then
     RBD="$RBD --keyfile ${CEPH_KEY}"
+    QEMU_OPTS="${QEMU_OPTS}:keyfile=${CEPH_KEY}"
 fi
 
 if [ -n "$CEPH_CONF" ]; then
     RBD="$RBD --conf ${CEPH_CONF}"
+    QEMU_OPTS="${QEMU_OPTS}:conf=${CEPH_CONF}"
 fi
 
 if [ "${TYPE}" = 'FILE' ]; then
@@ -111,9 +116,9 @@ if [ "${TYPE}" = 'FILE' ]; then
             $RBD resize $RBD_SRC --size $SIZE
         fi
 
-        $SUDO $RBD map $RBD_SRC
-        trap "$SUDO $RBD unmap /dev/rbd/$RBD_SRC" EXIT TERM INT HUP
-        $DD if=$SRC_PATH of=/dev/rbd/$RBD_SRC bs=64k
+        ${QEMU_IMG} convert -n \
+            -f raw "${SRC_PATH}" \
+            -O rbd "rbd:${RBD_SRC}${QEMU_OPTS}"
 EOF
 )
 else

From edd9b65956ddf4c8e8e82c901573327539d5b684 Mon Sep 17 00:00:00 2001
From: Stefan Kooman <stefan@bit.nl>
Date: Tue, 23 Jan 2018 17:19:16 +0100
Subject: [PATCH 3/6] Add CEPH_KEY to snap_revert driver operation (I missed
 this one apperently)

---
 src/tm_mad/ceph/snap_revert | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/tm_mad/ceph/snap_revert b/src/tm_mad/ceph/snap_revert
index 2029c688c7..25c88f8bf0 100755
--- a/src/tm_mad/ceph/snap_revert
+++ b/src/tm_mad/ceph/snap_revert
@@ -107,6 +107,10 @@ if [ -n "$CEPH_USER" ]; then
     RBD="$RBD --id ${CEPH_USER}"
 fi
 
+if [ -n "$CEPH_KEY" ]; then
+    RBD="$RBD --keyfile ${CEPH_KEY}"
+fi
+
 if [ -n "$CEPH_CONF" ]; then
     RBD="$RBD --conf ${CEPH_CONF}"
 fi

From 6d86753f648405b1365bd14482338f3730174c74 Mon Sep 17 00:00:00 2001
From: juanmont <jjmontiel@opennebula.org>
Date: Wed, 24 Jan 2018 15:33:12 +0100
Subject: [PATCH 4/6] F #1377: User locks for resources (#1675)

---
 include/AuthRequest.h                         |  12 +-
 include/PoolObjectAuth.h                      |   5 +-
 include/PoolObjectSQL.h                       |  57 +++-
 include/Request.h                             |   3 +-
 include/RequestManagerInfo.h                  |   2 +-
 include/RequestManagerLock.h                  | 257 +++++++++++++++++-
 include/RequestManagerVirtualMachine.h        |  11 +-
 src/acl/AclManager.cc                         |   9 +
 src/authm/AuthManager.cc                      |   2 +-
 src/cli/one_helper.rb                         |  17 ++
 src/cli/one_helper/oneimage_helper.rb         |   1 +
 src/cli/one_helper/onemarketapp_helper.rb     |   1 +
 src/cli/one_helper/onetemplate_helper.rb      |   1 +
 src/cli/one_helper/onevm_helper.rb            |   1 +
 src/cli/one_helper/onevmgroup_helper.rb       |   1 +
 src/cli/one_helper/onevnet_helper.rb          |   1 +
 src/cli/one_helper/onevrouter_helper.rb       |   1 +
 src/cli/oneimage                              |  64 +++++
 src/cli/onemarketapp                          |  64 +++++
 src/cli/onetemplate                           |  64 +++++
 src/cli/onevm                                 |  60 ++++
 src/cli/onevmgroup                            |  64 +++++
 src/cli/onevnet                               |  64 +++++
 src/cli/onevrouter                            |  64 +++++
 src/image/Image.cc                            |  12 +
 src/market/MarketPlaceApp.cc                  |   5 +
 .../org/opennebula/client/image/Image.java    |  48 ++++
 .../client/marketplaceapp/MarketPlaceApp.java |  48 ++++
 .../opennebula/client/template/Template.java  |  48 ++++
 .../opennebula/client/vmgroup/VMGroup.java    |  48 ++++
 .../client/vnet/VirtualNetwork.java           |  48 ++++
 .../client/vrouter/VirtualRouter.java         |  48 ++++
 src/oca/ruby/opennebula/image.rb              |  12 +-
 src/oca/ruby/opennebula/marketplaceapp.rb     |  14 +-
 src/oca/ruby/opennebula/template.rb           |  14 +-
 src/oca/ruby/opennebula/virtual_machine.rb    |  18 +-
 src/oca/ruby/opennebula/virtual_network.rb    |  12 +-
 src/oca/ruby/opennebula/virtual_router.rb     |  12 +
 src/oca/ruby/opennebula/vm_group.rb           |  14 +-
 src/pool/PoolObjectSQL.cc                     |  65 +++--
 src/rm/Request.cc                             |   8 +
 src/rm/RequestManager.cc                      |  35 ++-
 src/rm/RequestManagerLock.cc                  |  26 +-
 src/rm/RequestManagerVirtualMachine.cc        |   2 +-
 .../models/OpenNebulaJSON/ImageJSON.rb        |  10 +
 .../OpenNebulaJSON/MarketPlaceAppJSON.rb      |  10 +
 .../models/OpenNebulaJSON/TemplateJSON.rb     |  10 +
 .../models/OpenNebulaJSON/VMGroupJSON.rb      |  10 +
 .../OpenNebulaJSON/VirtualMachineJSON.rb      |  10 +
 .../OpenNebulaJSON/VirtualNetworkJSON.rb      |  10 +
 .../OpenNebulaJSON/VirtualRouterJSON.rb       |  10 +
 src/sunstone/public/app/opennebula/action.js  |   7 +
 src/sunstone/public/app/opennebula/image.js   |   6 +
 .../public/app/opennebula/marketplaceapp.js   |   6 +
 src/sunstone/public/app/opennebula/network.js |   8 +-
 .../public/app/opennebula/template.js         |   6 +
 .../public/app/opennebula/virtualrouter.js    |   6 +
 src/sunstone/public/app/opennebula/vm.js      |   6 +
 src/sunstone/public/app/opennebula/vmgroup.js |   6 +
 src/sunstone/public/app/sunstone.js           |  19 +-
 src/sunstone/public/app/sunstone/buttons.hbs  |   6 +
 src/sunstone/public/app/sunstone/tab.hbs      |   9 +-
 src/sunstone/public/app/tabs/acls-tab.js      |   1 +
 src/sunstone/public/app/tabs/clusters-tab.js  |   1 +
 .../public/app/tabs/datastores-tab.js         |   1 +
 src/sunstone/public/app/tabs/files-tab.js     |   1 +
 src/sunstone/public/app/tabs/groups-tab.js    |   1 +
 src/sunstone/public/app/tabs/hosts-tab.js     |   1 +
 src/sunstone/public/app/tabs/images-tab.js    |   1 +
 .../public/app/tabs/images-tab/actions.js     |   4 +
 .../public/app/tabs/images-tab/buttons.js     |  24 ++
 .../public/app/tabs/marketplaceapps-tab.js    |   1 +
 .../app/tabs/marketplaceapps-tab/actions.js   |   4 +
 .../app/tabs/marketplaceapps-tab/buttons.js   |  24 ++
 .../public/app/tabs/marketplaces-tab.js       |   1 +
 .../public/app/tabs/oneflow-services-tab.js   |   1 +
 .../public/app/tabs/oneflow-templates-tab.js  |   1 +
 src/sunstone/public/app/tabs/secgroups-tab.js |   1 +
 src/sunstone/public/app/tabs/templates-tab.js |   1 +
 .../app/tabs/templates-tab/actions-common.js  |  10 +-
 .../public/app/tabs/templates-tab/buttons.js  |  24 ++
 src/sunstone/public/app/tabs/users-tab.js     |   1 +
 src/sunstone/public/app/tabs/vdcs-tab.js      |   1 +
 src/sunstone/public/app/tabs/vmgroup-tab.js   |   1 +
 .../public/app/tabs/vmgroup-tab/actions.js    |   6 +-
 .../public/app/tabs/vmgroup-tab/buttons.js    |  24 ++
 src/sunstone/public/app/tabs/vms-tab.js       |   1 +
 .../public/app/tabs/vms-tab/actions.js        |   4 +
 .../public/app/tabs/vms-tab/buttons.js        |  23 ++
 .../public/app/tabs/vms-tab/hooks/header.js   |   9 +
 src/sunstone/public/app/tabs/vnets-tab.js     |   1 +
 .../public/app/tabs/vnets-tab/actions.js      |   4 +
 .../public/app/tabs/vnets-tab/buttons.js      |  24 ++
 .../public/app/tabs/vrouter-templates-tab.js  |   1 +
 src/sunstone/public/app/tabs/vrouters-tab.js  |   1 +
 .../public/app/tabs/vrouters-tab/actions.js   |   4 +
 .../public/app/tabs/vrouters-tab/buttons.js   |  24 ++
 src/sunstone/public/app/tabs/zones-tab.js     |   1 +
 src/sunstone/public/app/utils/hooks/header.js |   8 +
 src/sunstone/public/app/utils/humanize.js     |  25 +-
 src/vm/VirtualMachine.cc                      |   4 +
 src/vm_group/VMGroup.cc                       |   5 +
 src/vm_template/VMTemplate.cc                 |   3 +
 src/vnm/VirtualNetwork.cc                     |   4 +
 src/vrouter/VirtualRouter.cc                  |   5 +
 105 files changed, 1712 insertions(+), 93 deletions(-)

diff --git a/include/AuthRequest.h b/include/AuthRequest.h
index e5a0e92cac..f30317dc1a 100644
--- a/include/AuthRequest.h
+++ b/include/AuthRequest.h
@@ -46,10 +46,14 @@ public:
      */
     enum Operation
     {
-        USE    = 0x1LL,  /**< Auth. to use an object                   */
-        MANAGE = 0x2LL,  /**< Auth. to perform management actions      */
-        ADMIN  = 0x4LL,  /**< Auth. to perform administrative actions  */
-        CREATE = 0x8LL   /**< Auth. to create an object                */
+        USE           = 0x1LL,   /**< Auth. to use an object                   */
+        USE_NO_LCK    = 0x11LL,  /**< Auth. to use an object no lockable       */
+        MANAGE        = 0x2LL,   /**< Auth. to perform management actions      */
+        MANAGE_NO_LCK = 0x12LL,  /**< Auth. to perform management actions of an object no lockable */
+        ADMIN         = 0x4LL,   /**< Auth. to perform administrative actions  */
+        ADMIN_NO_LCK  = 0x14LL,  /**< Auth. to perform administrative actions of an object no lockable */
+        CREATE        = 0x8LL,   /**< Auth. to create an object                */
+        CREATE_NO_LCK = 0x18LL   /**< Auth. to create an object of an object no lockable */
     };
 
     static string operation_to_str(Operation op)
diff --git a/include/PoolObjectAuth.h b/include/PoolObjectAuth.h
index 79070e9dc3..2a6185f978 100644
--- a/include/PoolObjectAuth.h
+++ b/include/PoolObjectAuth.h
@@ -45,7 +45,8 @@ public:
         other_a(0),
         disable_all_acl(false),
         disable_cluster_acl(false),
-        disable_group_acl(false) {};
+        disable_group_acl(false),
+        locked(0) {};
 
     void get_acl_rules(AclRule& owner_rule,
                        AclRule& group_rule,
@@ -81,6 +82,8 @@ public:
     bool disable_all_acl;     // All objects of this type (e.g. NET/*)
     bool disable_cluster_acl; // All objects in a cluster (e.g. NET/%100)
     bool disable_group_acl;   // All objects own by this group (e.g. NET/@101)
+
+    int locked;
 };
 
 #endif /*POOL_OBJECT_AUTH_H_*/
diff --git a/include/PoolObjectSQL.h b/include/PoolObjectSQL.h
index d01d175c65..cd130d8ee4 100644
--- a/include/PoolObjectSQL.h
+++ b/include/PoolObjectSQL.h
@@ -70,6 +70,19 @@ public:
         VMGROUP        = 0x0020000000000000LL
     };
 
+    /**
+     *  OpenNebula objects. This definitions are used for define the level of lock
+     */
+    enum LockStates
+    {
+        ST_NONE      = 0x0LL,
+        ST_USE       = 0x1LL,
+        ST_MANAGE    = 0x2LL,
+        ST_ADMIN     = 0x4LL
+    };
+
+    static const long int LockableObject;
+
     static string type_to_str(ObjectType ob)
     {
         switch (ob)
@@ -96,6 +109,18 @@ public:
         }
     };
 
+    static string lock_state_to_str(LockStates ob)
+    {
+        switch (ob)
+        {
+            case ST_NONE:        return "NONE" ; break;
+            case ST_USE:         return "USE" ; break;
+            case ST_MANAGE:      return "MANAGE" ; break;
+            case ST_ADMIN:       return "ADMIN" ; break;
+            default:             return "";
+        }
+    };
+
     /* ---------------------------------------------------------------------- */
 
     PoolObjectSQL(int            id,
@@ -126,9 +151,10 @@ public:
              other_m(0),
              other_a(0),
              obj_template(0),
-             locked(false),
-             lock_owner(""),
-             lock_expires(0),
+             locked(LockStates::ST_NONE),
+             lock_owner(-1),
+             lock_req_id(-1),
+             lock_time(0),
              table(_table)
     {
         pthread_mutex_init(&mutex,0);
@@ -520,7 +546,7 @@ public:
      *
      * @return 0 if the lock was granted, -1 if the object is already locked
      */
-    int lock_db(const string& owner);
+    int lock_db(const int owner,const int req_id, const int level);
 
     /**
      * Unlocks the DB lock for external applications. The object must be locked
@@ -528,7 +554,17 @@ public:
      *
      * @param owner String to identify who requested the lock
      */
-    void unlock_db(const string& owner);
+    void unlock_db(const int owner, const int req_id);
+
+    /**
+     * Unlocks the DB lock for external applications. The object must be locked
+     * (internal memory mutex) before this method is called
+     *
+     * @param owner String to identify who requested the lock
+     */
+    LockStates get_lock_state(){
+        return locked;
+    }
 
 protected:
 
@@ -730,17 +766,22 @@ protected:
     /**
      *  Flag for the DB lock
      */
-    bool    locked;
+    LockStates    locked;
 
     /**
      *  Owner of the DB lock
      */
-    string  lock_owner;
+    int  lock_owner;
+
+    /**
+     *  Owner of the DB lock
+     */
+    int  lock_req_id;
 
     /**
      *  Expiration time for the DB lock
      */
-    time_t  lock_expires;
+    time_t  lock_time;
 
 private:
     /**
diff --git a/include/Request.h b/include/Request.h
index ad7e671ed5..b5f6ab2e65 100644
--- a/include/Request.h
+++ b/include/Request.h
@@ -131,7 +131,8 @@ public:
         ACTION         = 0x0800,
         XML_RPC_API    = 0x1000,
         INTERNAL       = 0x2000,
-        ALLOCATE       = 0x4000
+        ALLOCATE       = 0x4000,
+        LOCKED         = 0x8000
     };
 
     /**
diff --git a/include/RequestManagerInfo.h b/include/RequestManagerInfo.h
index 6c36e74af4..76ec93e6a5 100644
--- a/include/RequestManagerInfo.h
+++ b/include/RequestManagerInfo.h
@@ -33,7 +33,7 @@ protected:
                        const string& help)
         :Request(method_name, "A:si", help)
     {
-        auth_op = AuthRequest::USE;
+        auth_op = AuthRequest::USE_NO_LCK;
 
         leader_only = false;
     };
diff --git a/include/RequestManagerLock.h b/include/RequestManagerLock.h
index 55d6a91991..d690d3206a 100644
--- a/include/RequestManagerLock.h
+++ b/include/RequestManagerLock.h
@@ -33,7 +33,7 @@ protected:
                        const string& help)
         :Request(method_name, "A:sis", help)
     {
-        auth_op = AuthRequest::MANAGE;
+        auth_op = AuthRequest::MANAGE_NO_LCK;
     };
 
     ~RequestManagerLock(){};
@@ -43,7 +43,10 @@ protected:
     void request_execute(xmlrpc_c::paramList const& _paramList,
                          RequestAttributes& att);
 
-    virtual int lock_db(PoolObjectSQL * object, const string& owner) = 0;
+    int lock_db(PoolObjectSQL * object, const int owner, const int req_id, const int level)
+    {
+        return object->lock_db(owner, req_id, level);
+    };
 };
 
 /* ------------------------------------------------------------------------- */
@@ -54,9 +57,9 @@ class RequestManagerUnlock: public Request
 protected:
     RequestManagerUnlock(const string& method_name,
                          const string& help)
-        :Request(method_name, "A:sis", help)
+        :Request(method_name, "A:sii", help)
     {
-        auth_op = AuthRequest::MANAGE;
+        auth_op = AuthRequest::MANAGE_NO_LCK;
     };
 
     ~RequestManagerUnlock(){};
@@ -66,7 +69,10 @@ protected:
     void request_execute(xmlrpc_c::paramList const& _paramList,
                          RequestAttributes& att);
 
-    virtual void unlock_db(PoolObjectSQL * object, const string& owner) = 0;
+    void unlock_db(PoolObjectSQL * object, const int owner, const int req_id)
+    {
+        object->unlock_db(owner, req_id);
+    };
 };
 
 /* ------------------------------------------------------------------------- */
@@ -85,11 +91,6 @@ public:
     };
 
     ~DocumentLock(){};
-
-    int lock_db(PoolObjectSQL * object, const string& owner)
-    {
-        return static_cast<Document*>(object)->lock_db(owner);
-    };
 };
 
 /* ------------------------------------------------------------------------- */
@@ -108,15 +109,241 @@ public:
     };
 
     ~DocumentUnlock(){};
-
-    void unlock_db(PoolObjectSQL * object, const string& owner)
-    {
-        return static_cast<Document*>(object)->unlock_db(owner);
-    };
 };
 
 /* -------------------------------------------------------------------------- */
 /* -------------------------------------------------------------------------- */
+
+class VirtualMachineLock: public RequestManagerLock
+{
+public:
+    VirtualMachineLock():
+        RequestManagerLock("one.vm.lock",
+                           "Lock a VM"){
+        Nebula& nd  = Nebula::instance();
+        auth_object = PoolObjectSQL::VM;
+        pool        =  nd.get_vmpool();
+    };
+
+    ~VirtualMachineLock(){};
+};
+/* -------------------------------------------------------------------------- */
 /* -------------------------------------------------------------------------- */
 
+class VirtualMachineUnlock: public RequestManagerUnlock
+{
+public:
+    VirtualMachineUnlock():
+        RequestManagerUnlock("one.vm.unlock",
+                           "Unlock a VM"){
+        Nebula& nd  = Nebula::instance();
+        auth_object = PoolObjectSQL::VM;
+        pool        =  nd.get_vmpool();
+    };
+
+    ~VirtualMachineUnlock(){};
+};
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+class VMTemplateLock: public RequestManagerLock
+{
+public:
+    VMTemplateLock():
+        RequestManagerLock("one.template.lock",
+                           "Lock a Template"){
+        Nebula& nd  = Nebula::instance();
+        auth_object = PoolObjectSQL::TEMPLATE;
+        pool        =  nd.get_tpool();
+    };
+
+    ~VMTemplateLock(){};
+};
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+class VMTemplateUnlock: public RequestManagerUnlock
+{
+public:
+    VMTemplateUnlock():
+        RequestManagerUnlock("one.template.unlock",
+                           "Unlock a Template"){
+        Nebula& nd  = Nebula::instance();
+        auth_object = PoolObjectSQL::TEMPLATE;
+        pool        =  nd.get_tpool();
+    };
+
+    ~VMTemplateUnlock(){};
+};
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+class VirtualNetworkLock: public RequestManagerLock
+{
+public:
+    VirtualNetworkLock():
+        RequestManagerLock("one.vn.lock",
+                           "Lock a VNet"){
+        Nebula& nd  = Nebula::instance();
+        auth_object = PoolObjectSQL::NET;
+        pool        =  nd.get_vnpool();
+    };
+
+    ~VirtualNetworkLock(){};
+};
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+class VirtualNetworkUnlock: public RequestManagerUnlock
+{
+public:
+    VirtualNetworkUnlock():
+        RequestManagerUnlock("one.vn.unlock",
+                           "Unlock a VNet"){
+        Nebula& nd  = Nebula::instance();
+        auth_object = PoolObjectSQL::NET;
+        pool        =  nd.get_vnpool();
+    };
+
+    ~VirtualNetworkUnlock(){};
+};
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+class ImageLock: public RequestManagerLock
+{
+public:
+    ImageLock():
+        RequestManagerLock("one.image.lock",
+                           "Lock a Image"){
+        Nebula& nd  = Nebula::instance();
+        auth_object = PoolObjectSQL::IMAGE;
+        pool        =  nd.get_ipool();
+    };
+
+    ~ImageLock(){};
+};
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+class ImageUnlock: public RequestManagerUnlock
+{
+public:
+    ImageUnlock():
+        RequestManagerUnlock("one.image.unlock",
+                           "Unlock a Image"){
+        Nebula& nd  = Nebula::instance();
+        auth_object = PoolObjectSQL::IMAGE;
+        pool        =  nd.get_ipool();
+    };
+
+    ~ImageUnlock(){};
+};
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+class MarketPlaceAppLock: public RequestManagerLock
+{
+public:
+    MarketPlaceAppLock():
+        RequestManagerLock("one.marketapp.lock",
+                           "Lock a MarketPlaceApp"){
+        Nebula& nd  = Nebula::instance();
+        auth_object = PoolObjectSQL::MARKETPLACEAPP;
+        pool        =  nd.get_apppool();
+    };
+
+    ~MarketPlaceAppLock(){};
+};
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+class MarketPlaceAppUnlock: public RequestManagerUnlock
+{
+public:
+    MarketPlaceAppUnlock():
+        RequestManagerUnlock("one.marketapp.unlock",
+                           "Unlock a MarketPlaceApp"){
+        Nebula& nd  = Nebula::instance();
+        auth_object = PoolObjectSQL::MARKETPLACEAPP;
+        pool        =  nd.get_apppool();
+    };
+
+    ~MarketPlaceAppUnlock(){};
+};
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+class VirtualRouterLock: public RequestManagerLock
+{
+public:
+    VirtualRouterLock():
+        RequestManagerLock("one.vrouter.lock",
+                           "Lock a VirtualRouter"){
+        Nebula& nd  = Nebula::instance();
+        auth_object = PoolObjectSQL::VROUTER;
+        pool        =  nd.get_vrouterpool();
+    };
+
+    ~VirtualRouterLock(){};
+};
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+class VirtualRouterUnlock: public RequestManagerUnlock
+{
+public:
+    VirtualRouterUnlock():
+        RequestManagerUnlock("one.vrouter.unlock",
+                           "Unlock a VirtualRouter"){
+        Nebula& nd  = Nebula::instance();
+        auth_object = PoolObjectSQL::VROUTER;
+        pool        =  nd.get_vrouterpool();
+    };
+
+    ~VirtualRouterUnlock(){};
+};
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+class VMGroupLock: public RequestManagerLock
+{
+public:
+    VMGroupLock():
+        RequestManagerLock("one.vmgroup.lock",
+                           "Lock a VMGroup"){
+        Nebula& nd  = Nebula::instance();
+        auth_object = PoolObjectSQL::VMGROUP;
+        pool        =  nd.get_vmgrouppool();
+    };
+
+    ~VMGroupLock(){};
+};
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+class VMGroupUnlock: public RequestManagerUnlock
+{
+public:
+    VMGroupUnlock():
+        RequestManagerUnlock("one.vmgroup.unlock",
+                           "Unlock a VMGroup"){
+        Nebula& nd  = Nebula::instance();
+        auth_object = PoolObjectSQL::VMGROUP;
+        pool        =  nd.get_vmgrouppool();
+    };
+
+    ~VMGroupUnlock(){};
+};
 #endif
diff --git a/include/RequestManagerVirtualMachine.h b/include/RequestManagerVirtualMachine.h
index 069df26e37..52e0ed3009 100644
--- a/include/RequestManagerVirtualMachine.h
+++ b/include/RequestManagerVirtualMachine.h
@@ -32,7 +32,7 @@ protected:
     RequestManagerVirtualMachine(const string& method_name,
                        const string& help,
                        const string& params)
-        :Request(method_name,params,help)
+        :Request(method_name, params, help)
     {
         Nebula& nd  = Nebula::instance();
         pool        = nd.get_vmpool();
@@ -193,13 +193,17 @@ public:
         RequestManagerVirtualMachine("one.vm.monitoring",
                 "Returns the virtual machine monitoring records",
                 "A:si"){
-        auth_op = AuthRequest::USE;
+        auth_op = AuthRequest::USE_NO_LCK;
     };
 
     ~VirtualMachineMonitoring(){};
 
     void request_execute(
             xmlrpc_c::paramList const& paramList, RequestAttributes& att);
+
+    virtual bool is_locked(xmlrpc_c::paramList const& paramList, RequestAttributes& att){
+        return false;
+    };
 };
 
 /* ------------------------------------------------------------------------- */
@@ -521,9 +525,6 @@ public:
             RequestAttributes& att);
 };
 
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-
 class VirtualMachineDiskResize : public RequestManagerVirtualMachine
 {
 public:
diff --git a/src/acl/AclManager.cc b/src/acl/AclManager.cc
index bb47f9053d..404809d1a8 100644
--- a/src/acl/AclManager.cc
+++ b/src/acl/AclManager.cc
@@ -228,6 +228,15 @@ const bool AclManager::authorize(
     long long user_req;
     long long resource_oid_req;
 
+    if (static_cast<long long int>(op) & 0x10LL) //No lockable object
+    {
+        op = static_cast<AuthRequest::Operation>(op & 0x0FLL);
+    }
+    else if (obj_perms.locked > 0 && obj_perms.locked <= static_cast<long long int>(op))
+    {
+        return false;
+    }
+
     if ( obj_perms.oid >= 0 )
     {
         resource_oid_req = obj_perms.obj_type |
diff --git a/src/authm/AuthManager.cc b/src/authm/AuthManager.cc
index 499678cee9..e91124839e 100644
--- a/src/authm/AuthManager.cc
+++ b/src/authm/AuthManager.cc
@@ -56,7 +56,7 @@ void AuthRequest::add_auth(Operation             op,
         oss << ob_perms.oid << ":";
     }
 
-    oss << operation_to_str(op) << ":";
+    oss << operation_to_str(static_cast<AuthRequest::Operation>(op & 0x0FLL)) << ":";
 
     oss << ob_perms.uid << ":";
 
diff --git a/src/cli/one_helper.rb b/src/cli/one_helper.rb
index d80e24e3b9..9b786703b7 100644
--- a/src/cli/one_helper.rb
+++ b/src/cli/one_helper.rb
@@ -1267,4 +1267,21 @@ EOT
             return OpenNebula::Error.new("Remote server error: #{error_message}")
         end
     end
+
+    def OpenNebulaHelper.level_lock_to_str(str)
+        level = str.to_i
+        if level == 0
+            "None"
+        elsif level == 1
+            "Use"
+        elsif level == 2
+            "Manage"
+        elsif level == 3
+            "Admin"
+        elsif level == 4
+            "All"
+        else
+            "-"
+        end
+    end
 end
diff --git a/src/cli/one_helper/oneimage_helper.rb b/src/cli/one_helper/oneimage_helper.rb
index fdb0ee0087..c72743b84c 100644
--- a/src/cli/one_helper/oneimage_helper.rb
+++ b/src/cli/one_helper/oneimage_helper.rb
@@ -265,6 +265,7 @@ class OneImageHelper < OpenNebulaHelper::OneHelper
         puts str % ["NAME", image.name]
         puts str % ["USER", image['UNAME']]
         puts str % ["GROUP",image['GNAME']]
+        puts str % ["LOCK", OpenNebulaHelper.level_lock_to_str(image['LOCK/LOCKED'])]
         puts str % ["DATASTORE",image['DATASTORE']]
         puts str % ["TYPE", image.type_str]
         puts str % ["REGISTER TIME",
diff --git a/src/cli/one_helper/onemarketapp_helper.rb b/src/cli/one_helper/onemarketapp_helper.rb
index 934b4c15f8..e0fbacfdde 100644
--- a/src/cli/one_helper/onemarketapp_helper.rb
+++ b/src/cli/one_helper/onemarketapp_helper.rb
@@ -150,6 +150,7 @@ class OneMarketPlaceAppHelper < OpenNebulaHelper::OneHelper
         puts str % ["GROUP", app['GNAME']]
         puts str % ["MARKETPLACE", app['MARKETPLACE']]
         puts str % ["STATE", OneMarketPlaceAppHelper.state_to_str(app["STATE"])]
+        puts str % ["LOCK", OpenNebulaHelper.level_lock_to_str(app['LOCK/LOCKED'])]
 
         puts
 
diff --git a/src/cli/one_helper/onetemplate_helper.rb b/src/cli/one_helper/onetemplate_helper.rb
index eefd1fa61b..f5ceb4426c 100644
--- a/src/cli/one_helper/onetemplate_helper.rb
+++ b/src/cli/one_helper/onetemplate_helper.rb
@@ -321,6 +321,7 @@ EOT
         puts str % ["NAME", template.name]
         puts str % ["USER", template['UNAME']]
         puts str % ["GROUP", template['GNAME']]
+        puts str % ["LOCK", OpenNebulaHelper.level_lock_to_str(template['LOCK/LOCKED'])]
         puts str % ["REGISTER TIME",
             OpenNebulaHelper.time_to_str(template['REGTIME'])]
         puts
diff --git a/src/cli/one_helper/onevm_helper.rb b/src/cli/one_helper/onevm_helper.rb
index 40b7da279b..6969dd6db0 100644
--- a/src/cli/one_helper/onevm_helper.rb
+++ b/src/cli/one_helper/onevm_helper.rb
@@ -516,6 +516,7 @@ in the frontend machine.
         puts str % ["GROUP", vm['GNAME']]
         puts str % ["STATE", vm.state_str]
         puts str % ["LCM_STATE", vm.lcm_state_str]
+        puts str % ["LOCK", OpenNebulaHelper.level_lock_to_str(vm['LOCK/LOCKED'])]
         puts str % ["RESCHED", OpenNebulaHelper.boolean_to_str(vm['RESCHED'])]
         puts str % ["HOST",
             vm['/VM/HISTORY_RECORDS/HISTORY[last()]/HOSTNAME']] if
diff --git a/src/cli/one_helper/onevmgroup_helper.rb b/src/cli/one_helper/onevmgroup_helper.rb
index 23dc54cce4..ea8c01ed11 100644
--- a/src/cli/one_helper/onevmgroup_helper.rb
+++ b/src/cli/one_helper/onevmgroup_helper.rb
@@ -102,6 +102,7 @@ class OneVMGroupHelper < OpenNebulaHelper::OneHelper
         puts str % ["NAME", vmgroup.name]
         puts str % ["USER", vmgroup['UNAME']]
         puts str % ["GROUP", vmgroup['GNAME']]
+        puts str % ["LOCK", OpenNebulaHelper.level_lock_to_str(vmgroup['LOCK/LOCKED'])]
 
         CLIHelper.print_header(str_h1 % "PERMISSIONS",false)
 
diff --git a/src/cli/one_helper/onevnet_helper.rb b/src/cli/one_helper/onevnet_helper.rb
index 2799f46eac..0647ceeb57 100644
--- a/src/cli/one_helper/onevnet_helper.rb
+++ b/src/cli/one_helper/onevnet_helper.rb
@@ -219,6 +219,7 @@ class OneVNetHelper < OpenNebulaHelper::OneHelper
         puts str % ["NAME", vn['NAME']]
         puts str % ["USER", vn['UNAME']]
         puts str % ["GROUP", vn['GNAME']]
+        puts str % ["LOCK", OpenNebulaHelper.level_lock_to_str(vn['LOCK/LOCKED'])]
         puts str % ["CLUSTERS",
             OpenNebulaHelper.clusters_str(vn.retrieve_elements("CLUSTERS/ID"))]
         puts str % ["BRIDGE", vn["BRIDGE"]]
diff --git a/src/cli/one_helper/onevrouter_helper.rb b/src/cli/one_helper/onevrouter_helper.rb
index c08d41a915..34a1f1f446 100644
--- a/src/cli/one_helper/onevrouter_helper.rb
+++ b/src/cli/one_helper/onevrouter_helper.rb
@@ -109,6 +109,7 @@ class OneVirtualRouterHelper < OpenNebulaHelper::OneHelper
         puts str % ["NAME", obj.name]
         puts str % ["USER", obj['UNAME']]
         puts str % ["GROUP", obj['GNAME']]
+        puts str % ["LOCK", OpenNebulaHelper.level_lock_to_str(obj['LOCK/LOCKED'])]
         puts
 
         CLIHelper.print_header(str_h1 % "PERMISSIONS",false)
diff --git a/src/cli/oneimage b/src/cli/oneimage
index fa0d6632b1..de9d2d8850 100755
--- a/src/cli/oneimage
+++ b/src/cli/oneimage
@@ -41,6 +41,30 @@ cmd=CommandParser::CmdParser.new(ARGV) do
         helper.set_client(options)
     end
 
+    USE={
+        :name  => "use",
+        :large => "--use",
+        :description => "lock use actions"
+    }
+
+    MANAGE={
+        :name  => "manage",
+        :large => "--manage",
+        :description => "lock manage actions"
+    }
+
+    ADMIN={
+        :name  => "admin",
+        :large => "--admin",
+        :description => "lock admin actions"
+    }
+
+    ALL={
+        :name  => "all",
+        :large => "--all",
+        :description => "lock all actions"
+    }
+
     ########################################################################
     # Global Options
     ########################################################################
@@ -357,4 +381,44 @@ cmd=CommandParser::CmdParser.new(ARGV) do
     command :top, top_desc, [:filterflag, nil], :options=>list_options do
         helper.list_pool(options, true, args[0])
     end
+
+    lock_desc = <<-EOT.unindent
+        Locks a VM with differents levels for lock any actions with this VM, show and
+        monitoring never will be locked.
+        Valid states are: All.
+        Levels:
+        [Use]: locks Admin, Manage and Use actions.
+        [Manage]: locks Manage and Use actions.
+        [Admin]: locks only Admin actions.
+    EOT
+
+    command :lock, lock_desc, :vmid,
+        :options => [USE, MANAGE, ADMIN, ALL] do
+        helper.perform_action(args[0],options,"Image locked") do |i|
+            if !options[:use].nil?
+                level = 1
+            elsif !options[:manage].nil?
+                level = 2
+            elsif !options[:admin].nil?
+                level = 3
+            elsif !options[:all].nil?
+                level = 4
+            else
+                STDERR.puts "Need to level of lock."
+                exit -1
+            end
+            i.lock(level)
+        end
+    end
+
+    unlock_desc = <<-EOT.unindent
+        Unlocks a VM for unlock any actions with this VM.
+        Valid states are: All.
+    EOT
+
+    command :unlock, unlock_desc, :vmid do
+        helper.perform_action(args[0],options,"Image unlocked") do |i|
+            i.unlock
+        end
+    end
 end
diff --git a/src/cli/onemarketapp b/src/cli/onemarketapp
index b209c4d567..7a34785782 100755
--- a/src/cli/onemarketapp
+++ b/src/cli/onemarketapp
@@ -44,6 +44,30 @@ CommandParser::CmdParser.new(ARGV) do
         helper.set_client(options)
     end
 
+    USE={
+        :name  => "use",
+        :large => "--use",
+        :description => "lock use actions"
+    }
+
+    MANAGE={
+        :name  => "manage",
+        :large => "--manage",
+        :description => "lock manage actions"
+    }
+
+    ADMIN={
+        :name  => "admin",
+        :large => "--admin",
+        :description => "lock admin actions"
+    }
+
+    ALL={
+        :name  => "all",
+        :large => "--all",
+        :description => "lock all actions"
+    }
+
     ########################################################################
     # Global Options
     ########################################################################
@@ -279,4 +303,44 @@ CommandParser::CmdParser.new(ARGV) do
             obj.disable
         end
     end
+
+    lock_desc = <<-EOT.unindent
+        Locks a VM with differents levels for lock any actions with this VM, show and
+        monitoring never will be locked.
+        Valid states are: All.
+        Levels:
+        [Use]: locks Admin, Manage and Use actions.
+        [Manage]: locks Manage and Use actions.
+        [Admin]: locks only Admin actions.
+    EOT
+
+    command :lock, lock_desc, :appid,
+        :options => [USE, MANAGE, ADMIN, ALL] do
+        helper.perform_action(args[0],options,"MarketPlaceApp locked") do |app|
+            if !options[:use].nil?
+                level = 1
+            elsif !options[:manage].nil?
+                level = 2
+            elsif !options[:admin].nil?
+                level = 3
+            elsif !options[:all].nil?
+                level = 4
+            else
+                STDERR.puts "Need to level of lock."
+                exit -1
+            end
+            app.lock(level)
+        end
+    end
+
+    unlock_desc = <<-EOT.unindent
+        Unlocks a VM for unlock any actions with this VM.
+        Valid states are: All.
+    EOT
+
+    command :unlock, unlock_desc, :vmid do
+        helper.perform_action(args[0],options,"MarketPlaceApp unlocked") do |app|
+            app.unlock
+        end
+    end
 end
diff --git a/src/cli/onetemplate b/src/cli/onetemplate
index b8a7b8aa5b..0e9ecb2957 100755
--- a/src/cli/onetemplate
+++ b/src/cli/onetemplate
@@ -41,6 +41,30 @@ cmd=CommandParser::CmdParser.new(ARGV) do
         helper.set_client(options)
     end
 
+    USE={
+        :name  => "use",
+        :large => "--use",
+        :description => "lock use actions"
+    }
+
+    MANAGE={
+        :name  => "manage",
+        :large => "--manage",
+        :description => "lock manage actions"
+    }
+
+    ADMIN={
+        :name  => "admin",
+        :large => "--admin",
+        :description => "lock admin actions"
+    }
+
+    ALL={
+        :name  => "all",
+        :large => "--all",
+        :description => "lock all actions"
+    }
+
     ########################################################################
     # Global Options
     ########################################################################
@@ -341,4 +365,44 @@ cmd=CommandParser::CmdParser.new(ARGV) do
     command :top, top_desc, [:filterflag, nil], :options=>list_options do
         helper.list_pool(options, true, args[0])
     end
+
+    lock_desc = <<-EOT.unindent
+        Locks a VM with differents levels for lock any actions with this VM, show and
+        monitoring never will be locked.
+        Valid states are: All.
+        Levels:
+        [Use]: locks Admin, Manage and Use actions.
+        [Manage]: locks Manage and Use actions.
+        [Admin]: locks only Admin actions.
+    EOT
+
+    command :lock, lock_desc, :templateid,
+        :options => [USE, MANAGE, ADMIN, ALL] do
+        helper.perform_action(args[0],options,"Template locked") do |t|
+            if !options[:use].nil?
+                level = 1
+            elsif !options[:manage].nil?
+                level = 2
+            elsif !options[:admin].nil?
+                level = 3
+            elsif !options[:all].nil?
+                level = 4
+            else
+                STDERR.puts "Need to level of lock."
+                exit -1
+            end
+            t.lock(level)
+        end
+    end
+
+    unlock_desc = <<-EOT.unindent
+        Unlocks a VM for unlock any actions with this VM.
+        Valid states are: All.
+    EOT
+
+    command :unlock, unlock_desc, :templateid do
+        helper.perform_action(args[0],options,"Template unlocked") do |t|
+            t.unlock
+        end
+    end
 end
diff --git a/src/cli/onevm b/src/cli/onevm
index dc1eedaff5..4e705eb010 100755
--- a/src/cli/onevm
+++ b/src/cli/onevm
@@ -137,6 +137,30 @@ cmd=CommandParser::CmdParser.new(ARGV) do
         :description => "Make the new images persistent"
     }
 
+    USE={
+        :name  => "use",
+        :large => "--use",
+        :description => "lock use actions"
+    }
+
+    MANAGE={
+        :name  => "manage",
+        :large => "--manage",
+        :description => "lock manage actions"
+    }
+
+    ADMIN={
+        :name  => "admin",
+        :large => "--admin",
+        :description => "lock admin actions"
+    }
+
+    ALL={
+        :name  => "all",
+        :large => "--all",
+        :description => "lock all actions"
+    }
+
     ########################################################################
     # Global Options
     ########################################################################
@@ -996,6 +1020,42 @@ cmd=CommandParser::CmdParser.new(ARGV) do
         end
     end
 
+    lock_desc = <<-EOT.unindent
+        Locks a VM with differents levels for lock any actions with this VM, show and
+        monitoring never will be locked.
+        Aalid states are: All.
+    EOT
+
+    command :lock, lock_desc, :vmid,
+        :options => [USE, MANAGE, ADMIN, ALL] do
+        helper.perform_action(args[0],options,"VM locked") do |vm|
+            if !options[:use].nil?
+                level = 1
+            elsif !options[:manage].nil?
+                level = 2
+            elsif !options[:admin].nil?
+                level = 3
+            elsif !options[:all].nil?
+                level = 4
+            else
+                STDERR.puts "Need to level of lock."
+                exit -1
+            end
+            vm.lock(level)
+        end
+    end
+
+    unlock_desc = <<-EOT.unindent
+        Unlocks a VM for unlock any actions with this VM.
+        Valid states are: All.
+    EOT
+
+    command :unlock, unlock_desc, :vmid do
+        helper.perform_action(args[0],options,"VM unlocked") do |vm|
+            vm.unlock
+        end
+    end
+
     # Deprecated commands
 
     deprecated_command(:shutdown, 'terminate')
diff --git a/src/cli/onevmgroup b/src/cli/onevmgroup
index a9edb33217..7e15c27e18 100755
--- a/src/cli/onevmgroup
+++ b/src/cli/onevmgroup
@@ -40,6 +40,30 @@ cmd=CommandParser::CmdParser.new(ARGV) do
         helper.set_client(options)
     end
 
+    USE={
+        :name  => "use",
+        :large => "--use",
+        :description => "lock use actions"
+    }
+
+    MANAGE={
+        :name  => "manage",
+        :large => "--manage",
+        :description => "lock manage actions"
+    }
+
+    ADMIN={
+        :name  => "admin",
+        :large => "--admin",
+        :description => "lock admin actions"
+    }
+
+    ALL={
+        :name  => "all",
+        :large => "--all",
+        :description => "lock all actions"
+    }
+
     ########################################################################
     # Global Options
     ########################################################################
@@ -182,4 +206,44 @@ cmd=CommandParser::CmdParser.new(ARGV) do
             o.rename(args[1])
         end
     end
+
+    lock_desc = <<-EOT.unindent
+        Locks a VM with differents levels for lock any actions with this VM, show and
+        monitoring never will be locked.
+        Valid states are: All.
+        Levels:
+        [Use]: locks Admin, Manage and Use actions.
+        [Manage]: locks Manage and Use actions.
+        [Admin]: locks only Admin actions.
+    EOT
+
+    command :lock, lock_desc, :vmid,
+        :options => [USE, MANAGE, ADMIN, ALL] do
+        helper.perform_action(args[0],options,"VMGroup locked") do |vmg|
+            if !options[:use].nil?
+                level = 1
+            elsif !options[:manage].nil?
+                level = 2
+            elsif !options[:admin].nil?
+                level = 3
+            elsif !options[:all].nil?
+                level = 4
+            else
+                STDERR.puts "Need to level of lock."
+                exit -1
+            end
+            vmg.lock(level)
+        end
+    end
+
+    unlock_desc = <<-EOT.unindent
+        Unlocks a VM for unlock any actions with this VM.
+        Valid states are: All.
+    EOT
+
+    command :unlock, unlock_desc, :vmid do
+        helper.perform_action(args[0],options,"VMGroup unlocked") do |vmg|
+            vmg.unlock
+        end
+    end
 end
diff --git a/src/cli/onevnet b/src/cli/onevnet
index d09e9ad7fc..3a5db4e529 100755
--- a/src/cli/onevnet
+++ b/src/cli/onevnet
@@ -41,6 +41,30 @@ cmd=CommandParser::CmdParser.new(ARGV) do
         helper.set_client(options)
     end
 
+    USE={
+        :name  => "use",
+        :large => "--use",
+        :description => "lock use actions"
+    }
+
+    MANAGE={
+        :name  => "manage",
+        :large => "--manage",
+        :description => "lock manage actions"
+    }
+
+    ADMIN={
+        :name  => "admin",
+        :large => "--admin",
+        :description => "lock admin actions"
+    }
+
+    ALL={
+        :name  => "all",
+        :large => "--all",
+        :description => "lock all actions"
+    }
+
     ########################################################################
     # Global Options
     ########################################################################
@@ -422,4 +446,44 @@ cmd=CommandParser::CmdParser.new(ARGV) do
             o.rename(args[1])
         end
     end
+
+    lock_desc = <<-EOT.unindent
+        Locks a VM with differents levels for lock any actions with this VM, show and
+        monitoring never will be locked.
+        Valid states are: All.
+        Levels:
+        [Use]: locks Admin, Manage and Use actions.
+        [Manage]: locks Manage and Use actions.
+        [Admin]: locks only Admin actions.
+    EOT
+
+    command :lock, lock_desc, :vnetid,
+        :options => [USE, MANAGE, ADMIN, ALL] do
+        helper.perform_action(args[0],options,"VNet locked") do |vnet|
+            if !options[:use].nil?
+                level = 1
+            elsif !options[:manage].nil?
+                level = 2
+            elsif !options[:admin].nil?
+                level = 3
+            elsif !options[:all].nil?
+                level = 4
+            else
+                STDERR.puts "Need to level of lock."
+                exit -1
+            end
+            vnet.lock(level)
+        end
+    end
+
+    unlock_desc = <<-EOT.unindent
+        Unlocks a VM for unlock any actions with this VM.
+        Valid states are: All.
+    EOT
+
+    command :unlock, unlock_desc, :vnetid do
+        helper.perform_action(args[0],options,"VNet unlocked") do |vnet|
+            vnet.unlock
+        end
+    end
 end
diff --git a/src/cli/onevrouter b/src/cli/onevrouter
index 5088fcd985..3a8c99d8a9 100755
--- a/src/cli/onevrouter
+++ b/src/cli/onevrouter
@@ -42,6 +42,30 @@ cmd=CommandParser::CmdParser.new(ARGV) do
         helper.set_client(options)
     end
 
+    USE={
+        :name  => "use",
+        :large => "--use",
+        :description => "lock use actions"
+    }
+
+    MANAGE={
+        :name  => "manage",
+        :large => "--manage",
+        :description => "lock manage actions"
+    }
+
+    ADMIN={
+        :name  => "admin",
+        :large => "--admin",
+        :description => "lock admin actions"
+    }
+
+    ALL={
+        :name  => "all",
+        :large => "--all",
+        :description => "lock all actions"
+    }
+
     ########################################################################
     # Global Options
     ########################################################################
@@ -314,4 +338,44 @@ cmd=CommandParser::CmdParser.new(ARGV) do
     command :top, top_desc, [:filterflag, nil], :options=>list_options do
         helper.list_pool(options, true, args[0])
     end
+
+    lock_desc = <<-EOT.unindent
+        Locks a VM with differents levels for lock any actions with this VM, show and
+        monitoring never will be locked.
+        Valid states are: All.
+        Levels:
+        [Use]: locks Admin, Manage and Use actions.
+        [Manage]: locks Manage and Use actions.
+        [Admin]: locks only Admin actions.
+    EOT
+
+    command :lock, lock_desc, :vmid,
+        :options => [USE, MANAGE, ADMIN, ALL] do
+        helper.perform_action(args[0],options,"VRouter locked") do |vr|
+            if !options[:use].nil?
+                level = 1
+            elsif !options[:manage].nil?
+                level = 2
+            elsif !options[:admin].nil?
+                level = 3
+            elsif !options[:all].nil?
+                level = 4
+            else
+                STDERR.puts "Need to level of lock."
+                exit -1
+            end
+            vr.lock(level)
+        end
+    end
+
+    unlock_desc = <<-EOT.unindent
+        Unlocks a VM for unlock any actions with this VM.
+        valid states are: All.
+    EOT
+
+    command :unlock, unlock_desc, :vmid do
+        helper.perform_action(args[0],options,"VRouter unlocked") do |vr|
+            vr.unlock
+        end
+    end
 end
diff --git a/src/image/Image.cc b/src/image/Image.cc
index 60a9ba4d93..7ad3f2b945 100644
--- a/src/image/Image.cc
+++ b/src/image/Image.cc
@@ -201,6 +201,7 @@ int Image::insert(SqlDB *db, string& error_str)
     }
 
     state = LOCKED; //LOCKED till the ImageManager copies it to the Repository
+    lock_db(-1,-1, PoolObjectSQL::LockStates::ST_USE);
 
     //--------------------------------------------------------------------------
     // Insert the Image
@@ -329,6 +330,7 @@ string& Image::to_xml(string& xml) const
     string        clone_collection_xml;
     string        app_clone_collection_xml;
     string        snapshots_xml;
+    string        lock_str;
 
     oss <<
         "<IMAGE>" <<
@@ -338,6 +340,7 @@ string& Image::to_xml(string& xml) const
             "<UNAME>"          << uname           << "</UNAME>"       <<
             "<GNAME>"          << gname           << "</GNAME>"       <<
             "<NAME>"           << name            << "</NAME>"        <<
+            lock_db_to_xml(lock_str)                                  <<
             perms_to_xml(perms_xml)                                   <<
             "<TYPE>"           << type            << "</TYPE>"        <<
             "<DISK_TYPE>"      << disk_type       << "</DISK_TYPE>"   <<
@@ -409,6 +412,7 @@ int Image::from_xml(const string& xml)
     rc += xpath(ds_id,          "/IMAGE/DATASTORE_ID",  -1);
     rc += xpath(ds_name,        "/IMAGE/DATASTORE",     "not_found");
 
+    rc += lock_db_from_xml();
     // Permissions
     rc += perms_from_xml();
 
@@ -804,6 +808,13 @@ void Image::set_state(ImageState _state)
         {
             lcm->trigger(LCMAction::DISK_LOCK_FAILURE, *i);
         }
+    } else if( _state == LOCKED)
+    {
+        lock_db(-1,-1, PoolObjectSQL::LockStates::ST_USE);
+    }
+    if (_state != LOCKED )
+    {
+        unlock_db(-1,-1);
     }
 
     state = _state;
@@ -820,6 +831,7 @@ void Image::set_state_unlock()
 
     switch (state) {
         case LOCKED:
+            unlock_db(-1,-1);
             set_state(READY);
             break;
 
diff --git a/src/market/MarketPlaceApp.cc b/src/market/MarketPlaceApp.cc
index e4dbd866c9..a08c230b27 100644
--- a/src/market/MarketPlaceApp.cc
+++ b/src/market/MarketPlaceApp.cc
@@ -222,6 +222,7 @@ std::string& MarketPlaceApp::to_xml(std::string& xml) const
 	std::ostringstream oss;
 	std::string        template_xml;
 	std::string        perm_str;
+    string lock_str;
 
     oss << "<MARKETPLACEAPP>"
 			"<ID>"             << oid           << "</ID>"  <<
@@ -229,6 +230,7 @@ std::string& MarketPlaceApp::to_xml(std::string& xml) const
 			"<GID>"            << gid           << "</GID>" <<
 			"<UNAME>"          << uname         << "</UNAME>" <<
 			"<GNAME>"          << gname         << "</GNAME>" <<
+            lock_db_to_xml(lock_str) <<
 			"<REGTIME>"        << regtime       << "</REGTIME>" <<
 			"<NAME>"           << name          << "</NAME>" <<
             "<ZONE_ID>"   << one_util::escape_xml(zone_id)  << "</ZONE_ID>" <<
@@ -294,6 +296,9 @@ int MarketPlaceApp::from_xml(const std::string &xml_str)
 	// ----- Permissions -----
     rc += perms_from_xml();
 
+    // ------ Lock -------
+    rc += lock_db_from_xml();
+
 	// ----- TEMPLATE -----
     ObjectXML::get_nodes("/MARKETPLACEAPP/TEMPLATE", content);
 
diff --git a/src/oca/java/src/org/opennebula/client/image/Image.java b/src/oca/java/src/org/opennebula/client/image/Image.java
index 8690508429..087f0214cf 100644
--- a/src/oca/java/src/org/opennebula/client/image/Image.java
+++ b/src/oca/java/src/org/opennebula/client/image/Image.java
@@ -42,6 +42,8 @@ public class Image extends PoolElement
     private static final String SNAPSHOTDELETE  = METHOD_PREFIX + "snapshotdelete";
     private static final String SNAPSHOTREVERT  = METHOD_PREFIX + "snapshotrevert";
     private static final String SNAPSHOTFLATTEN = METHOD_PREFIX + "snapshotflatten";
+    private static final String LOCK        = METHOD_PREFIX + "lock";
+    private static final String UNLOCK      = METHOD_PREFIX + "unlock";
 
     private static final String[] IMAGE_STATES =
         {"INIT", "READY", "USED", "DISABLED", "LOCKED",
@@ -323,6 +325,31 @@ public class Image extends PoolElement
         return client.call(SNAPSHOTFLATTEN, id, snapId);
     }
 
+    /**
+     * lock this Image
+     *
+     * @param client XML-RPC Client.
+     * @param id The Image id.
+     * @param level Lock level.
+     * @return If an error occurs the error message contains the reason.
+     */
+    public static OneResponse lock(Client client, int id, int level)
+    {
+        return client.call(LOCK, id, level);
+    }
+
+    /**
+     * Unlock this Image
+     *
+     * @param client XML-RPC Client.
+     * @param id The Image id.
+     * @return If an error occurs the error message contains the reason.
+     */
+    public static OneResponse unlock(Client client, int id)
+    {
+        return client.call(UNLOCK, id);
+    }
+
     // =================================
     // Instanced object XML-RPC methods
     // =================================
@@ -622,6 +649,27 @@ public class Image extends PoolElement
         return snapshotFlatten(client, id, snapId);
     }
 
+    /**
+     * Lock this Image
+     *
+     * @param level Lock level.
+     * @return If an error occurs the error message contains the reason.
+     */
+    public OneResponse lock(int level)
+    {
+        return rename(client, id, level);
+    }
+
+    /**
+     * Unlock this Image
+     *
+     * @return If an error occurs the error message contains the reason.
+     */
+    public OneResponse unlock()
+    {
+        return rename(client, id);
+    }
+
     // =================================
     // Helpers
     // =================================
diff --git a/src/oca/java/src/org/opennebula/client/marketplaceapp/MarketPlaceApp.java b/src/oca/java/src/org/opennebula/client/marketplaceapp/MarketPlaceApp.java
index a7ef69698b..ee0d47d079 100644
--- a/src/oca/java/src/org/opennebula/client/marketplaceapp/MarketPlaceApp.java
+++ b/src/oca/java/src/org/opennebula/client/marketplaceapp/MarketPlaceApp.java
@@ -36,6 +36,8 @@ public class MarketPlaceApp extends PoolElement
     private static final String CHOWN       = METHOD_PREFIX + "chown";
     private static final String CHMOD       = METHOD_PREFIX + "chmod";
     private static final String RENAME      = METHOD_PREFIX + "rename";
+    private static final String LOCK        = METHOD_PREFIX + "lock";
+    private static final String UNLOCK      = METHOD_PREFIX + "unlock";
 
     private static final String[] MARKETPLACEAPP_STATES =
         {"INIT", "READY", "LOCKED", "ERROR", "DISABLED"};
@@ -222,6 +224,31 @@ public class MarketPlaceApp extends PoolElement
         return client.call(RENAME, id, name);
     }
 
+    /**
+     * lock this MarketPlaceApp
+     *
+     * @param client XML-RPC Client.
+     * @param id The MarketPlaceApp id.
+     * @param level Lock level.
+     * @return If an error occurs the error message contains the reason.
+     */
+    public static OneResponse lock(Client client, int id, int level)
+    {
+        return client.call(LOCK, id, level);
+    }
+
+    /**
+     * Unlock this MarketPlaceApp
+     *
+     * @param client XML-RPC Client.
+     * @param id The MarketPlaceApp id.
+     * @return If an error occurs the error message contains the reason.
+     */
+    public static OneResponse unlock(Client client, int id)
+    {
+        return client.call(UNLOCK, id);
+    }
+
     // =================================
     // Instanced object XML-RPC methods
     // =================================
@@ -394,6 +421,27 @@ public class MarketPlaceApp extends PoolElement
         return rename(client, id, name);
     }
 
+    /**
+     * Lock this MarketPlaceApp
+     *
+     * @param level Lock level.
+     * @return If an error occurs the error message contains the reason.
+     */
+    public OneResponse lock(int level)
+    {
+        return rename(client, id, level);
+    }
+
+    /**
+     * Unlock this MarketPlaceApp
+     *
+     * @return If an error occurs the error message contains the reason.
+     */
+    public OneResponse unlock()
+    {
+        return rename(client, id);
+    }
+
     // =================================
     // Helpers
     // =================================
diff --git a/src/oca/java/src/org/opennebula/client/template/Template.java b/src/oca/java/src/org/opennebula/client/template/Template.java
index f115abb323..1953d1b37e 100644
--- a/src/oca/java/src/org/opennebula/client/template/Template.java
+++ b/src/oca/java/src/org/opennebula/client/template/Template.java
@@ -37,6 +37,8 @@ public class Template extends PoolElement
     private static final String INSTANTIATE = METHOD_PREFIX + "instantiate";
     private static final String CLONE    = METHOD_PREFIX + "clone";
     private static final String RENAME   = METHOD_PREFIX + "rename";
+    private static final String LOCK     = METHOD_PREFIX + "lock";
+    private static final String UNLOCK   = METHOD_PREFIX + "unlock";
 
     /**
      * Creates a new Template representation.
@@ -352,6 +354,31 @@ public class Template extends PoolElement
         return client.call(RENAME, id, name);
     }
 
+    /**
+     * lock this template
+     *
+     * @param client XML-RPC Client.
+     * @param id The template id.
+     * @param level Lock level.
+     * @return If an error occurs the error message contains the reason.
+     */
+    public static OneResponse lock(Client client, int id, int level)
+    {
+        return client.call(LOCK, id, level);
+    }
+
+    /**
+     * Unlock this template
+     *
+     * @param client XML-RPC Client.
+     * @param id The template id.
+     * @return If an error occurs the error message contains the reason.
+     */
+    public static OneResponse unlock(Client client, int id)
+    {
+        return client.call(UNLOCK, id);
+    }
+
     // =================================
     // Instanced object XML-RPC methods
     // =================================
@@ -666,6 +693,27 @@ public class Template extends PoolElement
         return rename(client, id, name);
     }
 
+    /**
+     * Lock this template
+     *
+     * @param level Lock level.
+     * @return If an error occurs the error message contains the reason.
+     */
+    public OneResponse lock(int level)
+    {
+        return rename(client, id, level);
+    }
+
+    /**
+     * Unlock this template
+     *
+     * @return If an error occurs the error message contains the reason.
+     */
+    public OneResponse unlock()
+    {
+        return rename(client, id);
+    }
+
     // =================================
     // Helpers
     // =================================
diff --git a/src/oca/java/src/org/opennebula/client/vmgroup/VMGroup.java b/src/oca/java/src/org/opennebula/client/vmgroup/VMGroup.java
index d18d654b84..ef83e94d77 100644
--- a/src/oca/java/src/org/opennebula/client/vmgroup/VMGroup.java
+++ b/src/oca/java/src/org/opennebula/client/vmgroup/VMGroup.java
@@ -35,6 +35,8 @@ public class VMGroup extends PoolElement{
     private static final String CHOWN           = METHOD_PREFIX + "chown";
     private static final String CHMOD           = METHOD_PREFIX + "chmod";
     private static final String RENAME          = METHOD_PREFIX + "rename";
+    private static final String LOCK            = METHOD_PREFIX + "lock";
+    private static final String UNLOCK          = METHOD_PREFIX + "unlock";
 
     /**
      * Creates a new vmgroup representation.
@@ -197,6 +199,31 @@ public class VMGroup extends PoolElement{
         return client.call(RENAME, id, name);
     }
 
+    /**
+     * lock this vmgroup
+     *
+     * @param client XML-RPC Client.
+     * @param id The id of the target vmgroup.
+     * @param level Lock level.
+     * @return If an error occurs the error message contains the reason.
+     */
+    public static OneResponse lock(Client client, int id, int level)
+    {
+        return client.call(LOCK, id, level);
+    }
+
+    /**
+     * Unlock this vmgroup
+     *
+     * @param client XML-RPC Client.
+     * @param id The id of the target vmgroup.
+     * @return If an error occurs the error message contains the reason.
+     */
+    public static OneResponse unlock(Client client, int id)
+    {
+        return client.call(UNLOCK, id);
+    }
+
     // =================================
     // Instanced object XML-RPC methods
     // =================================
@@ -338,6 +365,27 @@ public class VMGroup extends PoolElement{
         return rename(client, id, name);
     }
 
+    /**
+     * Lock this vmgroup
+     *
+     * @param level Lock level.
+     * @return If an error occurs the error message contains the reason.
+     */
+    public OneResponse lock(int level)
+    {
+        return rename(client, id, level);
+    }
+
+    /**
+     * Unlock this vmgroup
+     *
+     * @return If an error occurs the error message contains the reason.
+     */
+    public OneResponse unlock()
+    {
+        return rename(client, id);
+    }
+
     // =================================
     // Helpers
     // =================================
diff --git a/src/oca/java/src/org/opennebula/client/vnet/VirtualNetwork.java b/src/oca/java/src/org/opennebula/client/vnet/VirtualNetwork.java
index e3b8617dd5..398f58d366 100644
--- a/src/oca/java/src/org/opennebula/client/vnet/VirtualNetwork.java
+++ b/src/oca/java/src/org/opennebula/client/vnet/VirtualNetwork.java
@@ -42,6 +42,8 @@ public class VirtualNetwork extends PoolElement{
     private static final String RENAME          = METHOD_PREFIX + "rename";
     private static final String RESERVE         = METHOD_PREFIX + "reserve";
     private static final String FREEAR          = METHOD_PREFIX + "free_ar";
+    private static final String LOCK            = METHOD_PREFIX + "lock";
+    private static final String UNLOCK          = METHOD_PREFIX + "unlock";
 
     /**
      * Creates a new virtual network representation.
@@ -362,6 +364,31 @@ public class VirtualNetwork extends PoolElement{
         return client.call(FREEAR, id, arId);
     }
 
+    /**
+     * lock this virtual network
+     *
+     * @param client XML-RPC Client.
+     * @param id The virtual network id (nid)
+     * @param level Lock level.
+     * @return If an error occurs the error message contains the reason.
+     */
+    public static OneResponse lock(Client client, int id, int level)
+    {
+        return client.call(LOCK, id, level);
+    }
+
+    /**
+     * Unlock this virtual network
+     *
+     * @param client XML-RPC Client.
+     * @param id The virtual network id (nid)
+     * @return If an error occurs the error message contains the reason.
+     */
+    public static OneResponse unlock(Client client, int id)
+    {
+        return client.call(UNLOCK, id);
+    }
+
     // =================================
     // Instanced object XML-RPC methods
     // =================================
@@ -679,6 +706,27 @@ public class VirtualNetwork extends PoolElement{
         return free(client, id, arId);
     }
 
+    /**
+     * Lock this virtual network
+     *
+     * @param level Lock level.
+     * @return If an error occurs the error message contains the reason.
+     */
+    public OneResponse lock(int level)
+    {
+        return rename(client, id, level);
+    }
+
+    /**
+     * Unlock this virtual network
+     *
+     * @return If an error occurs the error message contains the reason.
+     */
+    public OneResponse unlock()
+    {
+        return rename(client, id);
+    }
+
     // =================================
     // Helpers
     // =================================
diff --git a/src/oca/java/src/org/opennebula/client/vrouter/VirtualRouter.java b/src/oca/java/src/org/opennebula/client/vrouter/VirtualRouter.java
index da003b1000..6c2d59bbeb 100644
--- a/src/oca/java/src/org/opennebula/client/vrouter/VirtualRouter.java
+++ b/src/oca/java/src/org/opennebula/client/vrouter/VirtualRouter.java
@@ -38,6 +38,8 @@ public class VirtualRouter extends PoolElement
     private static final String RENAME      = METHOD_PREFIX + "rename";
     private static final String ATTACHNIC   = METHOD_PREFIX + "attachnic";
     private static final String DETACHNIC   = METHOD_PREFIX + "detachnic";
+    private static final String LOCK        = METHOD_PREFIX + "lock";
+    private static final String UNLOCK      = METHOD_PREFIX + "unlock";
 
     /**
      * Creates a new VirtualRouter representation.
@@ -259,6 +261,31 @@ public class VirtualRouter extends PoolElement
         return client.call(DETACHNIC, id, nicId);
     }
 
+    /**
+     * lock this virtual router
+     *
+     * @param client XML-RPC Client.
+     * @param id The virtual router id.
+     * @param level Lock level.
+     * @return If an error occurs the error message contains the reason.
+     */
+    public static OneResponse lock(Client client, int id, int level)
+    {
+        return client.call(LOCK, id, level);
+    }
+
+    /**
+     * Unlock this virtual router
+     *
+     * @param client XML-RPC Client.
+     * @param id The virtual router id.
+     * @return If an error occurs the error message contains the reason.
+     */
+    public static OneResponse unlock(Client client, int id)
+    {
+        return client.call(UNLOCK, id);
+    }
+
     // =================================
     // Instanced object XML-RPC methods
     // =================================
@@ -485,6 +512,27 @@ public class VirtualRouter extends PoolElement
         return nicDetach(client, id, nicId);
     }
 
+    /**
+     * Lock this virtual router
+     *
+     * @param level Lock level.
+     * @return If an error occurs the error message contains the reason.
+     */
+    public OneResponse lock(int level)
+    {
+        return rename(client, id, level);
+    }
+
+    /**
+     * Unlock this virtual router
+     *
+     * @return If an error occurs the error message contains the reason.
+     */
+    public OneResponse unlock()
+    {
+        return rename(client, id);
+    }
+
     // =================================
     // Helpers
     // =================================
diff --git a/src/oca/ruby/opennebula/image.rb b/src/oca/ruby/opennebula/image.rb
index d434633f17..fbcfd50308 100644
--- a/src/oca/ruby/opennebula/image.rb
+++ b/src/oca/ruby/opennebula/image.rb
@@ -38,7 +38,9 @@ module OpenNebula
             :rename      => "image.rename",
             :snapshotdelete => "image.snapshotdelete",
             :snapshotrevert => "image.snapshotrevert",
-            :snapshotflatten=> "image.snapshotflatten"
+            :snapshotflatten=> "image.snapshotflatten",
+            :lock       => "image.lock",
+            :unlock     => "image.unlock"
         }
 
         IMAGE_STATES=%w{INIT READY USED DISABLED LOCKED ERROR CLONE DELETE
@@ -296,6 +298,14 @@ module OpenNebula
             self['GID'].to_i
         end
 
+        def lock(level)
+            return call(IMAGE_METHODS[:lock], @pe_id, level)
+        end
+
+        def unlock()
+            return call(IMAGE_METHODS[:unlock], @pe_id)
+        end
+
         def public?
             if self['PERMISSIONS/GROUP_U'] == "1" || self['PERMISSIONS/OTHER_U'] == "1"
                 true
diff --git a/src/oca/ruby/opennebula/marketplaceapp.rb b/src/oca/ruby/opennebula/marketplaceapp.rb
index 1c58f5a210..a0b1c48121 100644
--- a/src/oca/ruby/opennebula/marketplaceapp.rb
+++ b/src/oca/ruby/opennebula/marketplaceapp.rb
@@ -30,7 +30,9 @@ module OpenNebula
             :chown      => "marketapp.chown",
             :chmod      => "marketapp.chmod",
             :rename     => "marketapp.rename",
-            :enable     => "marketapp.enable"
+            :enable     => "marketapp.enable",
+            :lock       => "marketapp.lock",
+            :unlock     => "marketapp.unlock"
         }
 
         MARKETPLACEAPP_STATES=%w{INIT READY LOCKED ERROR DISABLED}
@@ -263,5 +265,15 @@ module OpenNebula
         def short_state_str
             SHORT_MARKETPLACEAPP_STATES[state_str]
         end
+
+        #Locked a MarketplaceApp
+        def lock(level)
+            return call(MARKETPLACEAPP_METHODS[:lock], @pe_id, level)
+        end
+
+        #Unlocked a MarketplaceApp
+        def unlock()
+            return call(MARKETPLACEAPP_METHODS[:unlock], @pe_id)
+        end
     end
 end
diff --git a/src/oca/ruby/opennebula/template.rb b/src/oca/ruby/opennebula/template.rb
index e089802058..cde90349b6 100644
--- a/src/oca/ruby/opennebula/template.rb
+++ b/src/oca/ruby/opennebula/template.rb
@@ -33,7 +33,9 @@ module OpenNebula
             :chown       => "template.chown",
             :chmod       => "template.chmod",
             :clone       => "template.clone",
-            :rename      => "template.rename"
+            :rename      => "template.rename",
+            :lock        => "template.lock",
+            :unlock      => "template.unlock"
         }
 
         # Creates a Template description with just its identifier
@@ -241,6 +243,16 @@ module OpenNebula
             self['UID'].to_i
         end
 
+        # Lock a Template
+        def lock(level)
+            return call(TEMPLATE_METHODS[:lock], @pe_id, level)
+        end
+
+        # Unlock a Template
+        def unlock()
+            return call(TEMPLATE_METHODS[:unlock], @pe_id)
+        end
+
         def public?
             if self['PERMISSIONS/GROUP_U'] == "1" || self['PERMISSIONS/OTHER_U'] == "1"
                 true
diff --git a/src/oca/ruby/opennebula/virtual_machine.rb b/src/oca/ruby/opennebula/virtual_machine.rb
index 2ae4f75c1d..4a4cfd23b9 100644
--- a/src/oca/ruby/opennebula/virtual_machine.rb
+++ b/src/oca/ruby/opennebula/virtual_machine.rb
@@ -47,7 +47,9 @@ module OpenNebula
             :disksnapshotrevert => "vm.disksnapshotrevert",
             :disksnapshotdelete => "vm.disksnapshotdelete",
             :diskresize     => "vm.diskresize",
-            :updateconf     => "vm.updateconf"
+            :updateconf     => "vm.updateconf",
+            :lock     => "vm.lock",
+            :unlock     => "vm.unlock"
         }
 
         VM_STATE=%w{INIT PENDING HOLD ACTIVE STOPPED SUSPENDED DONE FAILED
@@ -686,7 +688,17 @@ module OpenNebula
         #   otherwise
 		def updateconf(new_conf)
             return call(VM_METHODS[:updateconf], @pe_id, new_conf)
-		end
+        end
+
+        # Lock a VM
+        def lock(level)
+            return call(VM_METHODS[:lock], @pe_id, level)
+        end
+
+        # Unlock a VM
+        def unlock()
+            return call(VM_METHODS[:unlock], @pe_id)
+        end
 
         ########################################################################
         # Helpers to get VirtualMachine information
@@ -853,7 +865,7 @@ module OpenNebula
                     REMOVE_VNET_ATTRS.each do |attr|
                         nic.delete_element(attr)
                     end
-                    
+
                     replace << "NIC = [ " << nic.template_like_str(".").tr("\n", ",\n") << " ] \n"
                 end
 
diff --git a/src/oca/ruby/opennebula/virtual_network.rb b/src/oca/ruby/opennebula/virtual_network.rb
index af07aebc10..57aa62ca41 100644
--- a/src/oca/ruby/opennebula/virtual_network.rb
+++ b/src/oca/ruby/opennebula/virtual_network.rb
@@ -38,7 +38,9 @@ module OpenNebula
             :release    => "vn.release",
             :rename     => "vn.rename",
             :reserve    => "vn.reserve",
-            :free_ar    => "vn.free_ar"
+            :free_ar    => "vn.free_ar",
+            :lock       => "vn.lock",
+            :unlock     => "vn.unlock"
         }
 
         # Creates a VirtualNetwork description with just its identifier
@@ -330,6 +332,14 @@ module OpenNebula
             return array
         end
 
+        def lock(level)
+            return call(VN_METHODS[:lock], @pe_id, level)
+        end
+
+        def unlock()
+            return call(VN_METHODS[:unlock], @pe_id)
+        end
+
     private
         def set_publish(published)
             group_u = published ? 1 : 0
diff --git a/src/oca/ruby/opennebula/virtual_router.rb b/src/oca/ruby/opennebula/virtual_router.rb
index 73cf7f5a1a..4a6dfcdf2b 100644
--- a/src/oca/ruby/opennebula/virtual_router.rb
+++ b/src/oca/ruby/opennebula/virtual_router.rb
@@ -34,6 +34,8 @@ module OpenNebula
             :rename      => "vrouter.rename",
             :attachnic   => "vrouter.attachnic",
             :detachnic   => "vrouter.detachnic",
+            :lock        => "vrouter.lock",
+            :unlock      => "vrouter.unlock"
         }
 
         # Creates a VirtualRouter description with just its identifier
@@ -175,6 +177,16 @@ module OpenNebula
             return call(VIRTUAL_ROUTER_METHODS[:detachnic], @pe_id, nic_id)
         end
 
+        # Lock a VRouter
+        def lock(level)
+            return call(VIRTUAL_ROUTER_METHODS[:lock], @pe_id, level)
+        end
+
+        # Unlock a VRouter
+        def unlock()
+            return call(VIRTUAL_ROUTER_METHODS[:unlock], @pe_id)
+        end
+
         #######################################################################
         # Helpers to get VirtualRouter information
         #######################################################################
diff --git a/src/oca/ruby/opennebula/vm_group.rb b/src/oca/ruby/opennebula/vm_group.rb
index fc73df6d59..59c0da3812 100644
--- a/src/oca/ruby/opennebula/vm_group.rb
+++ b/src/oca/ruby/opennebula/vm_group.rb
@@ -28,7 +28,9 @@ module OpenNebula
             :delete      => "vmgroup.delete",
             :chown       => "vmgroup.chown",
             :chmod       => "vmgroup.chmod",
-            :rename      => "vmgroup.rename"
+            :rename      => "vmgroup.rename",
+            :lock        => "vmgroup.lock",
+            :unlock        => "vmgroup.unlock"
         }
 
         # Creates a VMGroup description with just its identifier
@@ -129,6 +131,16 @@ module OpenNebula
             return call(VMGROUP_METHODS[:rename], @pe_id, name)
         end
 
+        # Lock a VMGroup
+        def lock(level)
+            return call(VMGROUP_METHODS[:lock], @pe_id, level)
+        end
+
+        # Unlock a VMGroup
+        def unlock()
+            return call(VMGROUP_METHODS[:unlock], @pe_id)
+        end
+
         #######################################################################
         # Helpers to get VMGroup information
         #######################################################################
diff --git a/src/pool/PoolObjectSQL.cc b/src/pool/PoolObjectSQL.cc
index 49a21298db..d53a099eb2 100644
--- a/src/pool/PoolObjectSQL.cc
+++ b/src/pool/PoolObjectSQL.cc
@@ -24,6 +24,14 @@ const string PoolObjectSQL::INVALID_NAME_CHARS = "&|:\\\";/'#{}$<>";
 
 const int PoolObjectSQL::LOCK_DB_EXPIRATION = 120;
 
+const long int PoolObjectSQL::LockableObject = PoolObjectSQL::ObjectType::VM
+                                | PoolObjectSQL::ObjectType::TEMPLATE
+                                | PoolObjectSQL::ObjectType::IMAGE
+                                | PoolObjectSQL::ObjectType::MARKETPLACEAPP
+                                | PoolObjectSQL::ObjectType::NET
+                                | PoolObjectSQL::ObjectType::VROUTER
+                                | PoolObjectSQL::ObjectType::VMGROUP;
+
 /* -------------------------------------------------------------------------- */
 /* -------------------------------------------------------------------------- */
 
@@ -369,6 +377,8 @@ void PoolObjectSQL::get_permissions(PoolObjectAuth& auth)
     auth.other_m = other_m;
     auth.other_a = other_a;
 
+    auth.locked = static_cast<int>(locked);
+
     Clusterable* cl = dynamic_cast<Clusterable*>(this);
 
     if(cl != 0)
@@ -511,16 +521,12 @@ bool PoolObjectSQL::name_is_valid(const string& obj_name,
 /* -------------------------------------------------------------------------- */
 /* -------------------------------------------------------------------------- */
 
-int PoolObjectSQL::lock_db(const string& owner)
+int PoolObjectSQL::lock_db(const int owner, const int req_id, const int level)
 {
-    if (locked && time(0) < lock_expires)
-    {
-        return -1;
-    }
-
-    locked       = true;
-    lock_expires = time(0) + LOCK_DB_EXPIRATION;
+    locked       = static_cast<LockStates>(level);
+    lock_time = time(0);
     lock_owner   = owner;
+    lock_req_id  = req_id;
 
     return 0;
 }
@@ -528,13 +534,15 @@ int PoolObjectSQL::lock_db(const string& owner)
 /* -------------------------------------------------------------------------- */
 /* -------------------------------------------------------------------------- */
 
-void PoolObjectSQL::unlock_db(const string& owner)
+void PoolObjectSQL::unlock_db(const int owner, const int req_id)
 {
-    // Check if owner == lock_owner?
-
-    locked       = false;
-    lock_expires = 0;
-    lock_owner   = "";
+    if ( owner == lock_owner )
+    {
+        locked       = LockStates::ST_NONE;
+        lock_time = time(0);
+        lock_owner   = -1;
+        lock_req_id  = -1;
+    }
 }
 
 /* -------------------------------------------------------------------------- */
@@ -543,13 +551,15 @@ void PoolObjectSQL::unlock_db(const string& owner)
 string& PoolObjectSQL::lock_db_to_xml(string& xml) const
 {
     ostringstream   oss;
-    int locked_int = locked ? 1 : 0;
-
-    oss << "<LOCK>"
-            << "<LOCKED>"  << locked_int   << "</LOCKED>"
-            << "<OWNER>"   << one_util::escape_xml(lock_owner) << "</OWNER>"
-            << "<EXPIRES>" << lock_expires << "</EXPIRES>"
-        << "</LOCK>";
+    if (locked  != LockStates::ST_NONE)
+    {
+        oss << "<LOCK>"
+                << "<LOCKED>"  << static_cast<int>(locked)   << "</LOCKED>"
+                << "<OWNER>"   << lock_owner << "</OWNER>"
+                << "<TIME>" << lock_time << "</TIME>"
+                << "<REQ_ID>" << lock_req_id << "</REQ_ID>"
+            << "</LOCK>";
+    }
 
     xml = oss.str();
     return xml;
@@ -562,12 +572,17 @@ int PoolObjectSQL::lock_db_from_xml()
 {
     int rc = 0;
     int locked_int;
+    vector<xmlNodePtr> content;
 
-    rc += xpath(locked_int,   "/*/LOCK/LOCKED", 0);
-    rc += xpath(lock_owner,   "/*/LOCK/OWNER", "");
-    rc += xpath<time_t>(lock_expires, "/*/LOCK/EXPIRES", 0);
+    if (ObjectXML::get_nodes("/*/LOCK/LOCKED", content) > 0)
+    {
+        rc += xpath(locked_int,   "/*/LOCK/LOCKED", 0);
+        rc += xpath(lock_req_id,   "/*/LOCK/REQ_ID", -1);
+        rc += xpath(lock_owner,   "/*/LOCK/OWNER", -1);
+        xpath<time_t>(lock_time, "/*/LOCK/TIME", time(0));
 
-    locked = locked_int;
+        locked = static_cast<LockStates>(locked_int);
+    }
 
     return rc;
 }
diff --git a/src/rm/Request.cc b/src/rm/Request.cc
index b7833d33a9..0685cfce17 100644
--- a/src/rm/Request.cc
+++ b/src/rm/Request.cc
@@ -722,6 +722,14 @@ string Request::failure_message(ErrorCode ec, RequestAttributes& att)
                 oss << " " << att.resp_msg;
             }
             break;
+        case LOCKED:
+            oss << "The resource " << obname << " is locked.";
+
+            if ( att.resp_id != -1 )
+            {
+               oss << " [" << att.resp_id << "].";
+            }
+            break;
     }
 
     return oss.str();
diff --git a/src/rm/RequestManager.cc b/src/rm/RequestManager.cc
index a94c9e1f71..3a06d74b22 100644
--- a/src/rm/RequestManager.cc
+++ b/src/rm/RequestManager.cc
@@ -382,6 +382,18 @@ void RequestManager::register_xml_methods()
     // Lock Methods
     xmlrpc_c::methodPtr doc_lock(new DocumentLock());
     xmlrpc_c::methodPtr doc_unlock(new DocumentUnlock());
+    xmlrpc_c::methodPtr vm_lock(new VirtualMachineLock());
+    xmlrpc_c::methodPtr vm_unlock(new VirtualMachineUnlock());
+    xmlrpc_c::methodPtr template_lock(new VMTemplateLock());
+    xmlrpc_c::methodPtr template_unlock(new VMTemplateUnlock());
+    xmlrpc_c::methodPtr vn_lock(new VirtualNetworkLock());
+    xmlrpc_c::methodPtr vn_unlock(new VirtualNetworkUnlock());
+    xmlrpc_c::methodPtr image_lock(new ImageLock());
+    xmlrpc_c::methodPtr image_unlock(new ImageUnlock());
+    xmlrpc_c::methodPtr vrouter_lock(new VirtualRouterLock());
+    xmlrpc_c::methodPtr vrouter_unlock(new VirtualRouterUnlock());
+    xmlrpc_c::methodPtr vmg_lock(new VMGroupLock());
+    xmlrpc_c::methodPtr vmg_unlock(new VMGroupUnlock());
 
     // PoolInfo Methods
     xmlrpc_c::methodPtr hostpool_info(new HostPoolInfo());
@@ -495,6 +507,8 @@ void RequestManager::register_xml_methods()
     RequestManagerRegistry.addMethod("one.vm.disksnapshotdelete", vm_dsnap_delete);
     RequestManagerRegistry.addMethod("one.vm.recover", vm_recover);
     RequestManagerRegistry.addMethod("one.vm.updateconf", vm_updateconf);
+    RequestManagerRegistry.addMethod("one.vm.lock", vm_lock);
+    RequestManagerRegistry.addMethod("one.vm.unlock", vm_unlock);
     RequestManagerRegistry.addMethod("one.vm.diskresize", vm_disk_resize);
 
     RequestManagerRegistry.addMethod("one.vmpool.info", vm_pool_info);
@@ -513,7 +527,8 @@ void RequestManager::register_xml_methods()
     RequestManagerRegistry.addMethod("one.template.chmod", template_chmod);
     RequestManagerRegistry.addMethod("one.template.clone", template_clone);
     RequestManagerRegistry.addMethod("one.template.rename", template_rename);
-
+    RequestManagerRegistry.addMethod("one.template.lock", template_lock);
+    RequestManagerRegistry.addMethod("one.template.unlock", template_unlock);
     RequestManagerRegistry.addMethod("one.templatepool.info",template_pool_info);
 
     /* Host related methods*/
@@ -593,6 +608,8 @@ void RequestManager::register_xml_methods()
     RequestManagerRegistry.addMethod("one.vn.chown", vn_chown);
     RequestManagerRegistry.addMethod("one.vn.chmod", vn_chmod);
     RequestManagerRegistry.addMethod("one.vn.rename", vn_rename);
+    RequestManagerRegistry.addMethod("one.vn.lock", vn_lock);
+    RequestManagerRegistry.addMethod("one.vn.unlock", vn_unlock);
 
     RequestManagerRegistry.addMethod("one.vnpool.info", vnpool_info);
 
@@ -685,6 +702,8 @@ void RequestManager::register_xml_methods()
     RequestManagerRegistry.addMethod("one.image.snapshotdelete", image_snap_delete);
     RequestManagerRegistry.addMethod("one.image.snapshotrevert", image_snap_revert);
     RequestManagerRegistry.addMethod("one.image.snapshotflatten", image_snap_flatten);
+    RequestManagerRegistry.addMethod("one.image.lock", image_lock);
+    RequestManagerRegistry.addMethod("one.image.unlock", image_unlock);
 
     RequestManagerRegistry.addMethod("one.imagepool.info", imagepool_info);
 
@@ -833,6 +852,8 @@ void RequestManager::register_xml_methods()
     RequestManagerRegistry.addMethod("one.vmgroup.chmod",    vmg_chmod);
     RequestManagerRegistry.addMethod("one.vmgroup.rename",   vmg_rename);
     RequestManagerRegistry.addMethod("one.vmgroup.update",   vmg_update);
+    RequestManagerRegistry.addMethod("one.vmgroup.lock",     vmg_lock);
+    RequestManagerRegistry.addMethod("one.vmgroup.unlock",   vmg_unlock);
 
     RequestManagerRegistry.addMethod("one.vmgrouppool.info", vmgpool_info);
 
@@ -943,6 +964,8 @@ void RequestManager::register_xml_methods()
     RequestManagerRegistry.addMethod("one.vrouter.instantiate",vrouter_instantiate);
     RequestManagerRegistry.addMethod("one.vrouter.attachnic", vrouter_attachnic);
     RequestManagerRegistry.addMethod("one.vrouter.detachnic", vrouter_detachnic);
+    RequestManagerRegistry.addMethod("one.vrouter.lock", vrouter_lock);
+    RequestManagerRegistry.addMethod("one.vrouter.unlock", vrouter_unlock);
 
     RequestManagerRegistry.addMethod("one.vrouterpool.info",vrouter_pool_info);
 
@@ -1008,6 +1031,8 @@ void RequestManager::register_xml_methods()
     xmlrpc_c::method * marketapp_chown_pt;
     xmlrpc_c::method * marketapp_enable_pt;
     xmlrpc_c::method * marketapp_rename_pt;
+    xmlrpc_c::method * marketapp_lock_pt;
+    xmlrpc_c::method * marketapp_unlock_pt;
 
     if (nebula.is_federation_slave())
     {
@@ -1016,6 +1041,8 @@ void RequestManager::register_xml_methods()
         marketapp_chown_pt    = new RequestManagerProxy("one.marketapp.chown");
         marketapp_enable_pt   = new RequestManagerProxy("one.marketapp.enable");
         marketapp_rename_pt   = new RequestManagerProxy("one.marketapp.rename");
+        marketapp_lock_pt   = new RequestManagerProxy("one.marketapp.lock");
+        marketapp_unlock_pt   = new RequestManagerProxy("one.marketapp.unlock");
     }
     else
     {
@@ -1024,6 +1051,8 @@ void RequestManager::register_xml_methods()
         marketapp_chown_pt    = new MarketPlaceAppChown();
         marketapp_enable_pt   = new MarketPlaceAppEnable();
         marketapp_rename_pt   = new MarketPlaceAppRename();
+        marketapp_lock_pt   = new MarketPlaceAppLock();
+        marketapp_unlock_pt   = new MarketPlaceAppUnlock();
 
         xmlrpc_c::methodPtr marketapp_updatedb(new MarketPlaceAppUpdateDB());
         xmlrpc_c::methodPtr marketapp_dropdb(new MarketPlaceAppDropDB());
@@ -1046,6 +1075,8 @@ void RequestManager::register_xml_methods()
     xmlrpc_c::methodPtr marketapp_chown(marketapp_chown_pt);
     xmlrpc_c::methodPtr marketapp_enable(marketapp_enable_pt);
     xmlrpc_c::methodPtr marketapp_rename(marketapp_rename_pt);
+    xmlrpc_c::methodPtr marketapp_lock(marketapp_lock_pt);
+    xmlrpc_c::methodPtr marketapp_unlock(marketapp_unlock_pt);
 
     xmlrpc_c::methodPtr marketapp_info(new MarketPlaceAppInfo());
     xmlrpc_c::methodPtr marketapppool_info(new MarketPlaceAppPoolInfo());
@@ -1056,6 +1087,8 @@ void RequestManager::register_xml_methods()
     RequestManagerRegistry.addMethod("one.marketapp.chmod", marketapp_chmod);
     RequestManagerRegistry.addMethod("one.marketapp.chown", marketapp_chown);
     RequestManagerRegistry.addMethod("one.marketapp.enable", marketapp_enable);
+    RequestManagerRegistry.addMethod("one.marketapp.lock", marketapp_lock);
+    RequestManagerRegistry.addMethod("one.marketapp.unlock", marketapp_unlock);
 
     RequestManagerRegistry.addMethod("one.marketapp.info", marketapp_info);
     RequestManagerRegistry.addMethod("one.marketapp.rename", marketapp_rename);
diff --git a/src/rm/RequestManagerLock.cc b/src/rm/RequestManagerLock.cc
index 3e2a37c986..64e7092755 100644
--- a/src/rm/RequestManagerLock.cc
+++ b/src/rm/RequestManagerLock.cc
@@ -25,8 +25,8 @@ void RequestManagerLock::request_execute(xmlrpc_c::paramList const& paramList,
                                          RequestAttributes& att)
 {
     int     oid     = xmlrpc_c::value_int(paramList.getInt(1));
-    string  owner   = xmlrpc_c::value_string(paramList.getString(2));
-
+    int level   = xmlrpc_c::value_int(paramList.getInt(2));
+    int owner = att.uid;
     PoolObjectSQL * object;
     string          error_str;
     int             rc;
@@ -45,13 +45,22 @@ void RequestManagerLock::request_execute(xmlrpc_c::paramList const& paramList,
         return;
     }
 
-    rc = lock_db(object, owner);
+    if ((auth_object & PoolObjectSQL::LockableObject) != 0)
+    {
+        rc = lock_db(object, owner, att.req_id, level);
 
-    pool->update(object);
+        pool->update(object);
 
-    object->unlock();
+        object->unlock();
 
-    success_response((rc == 0), att);
+        success_response((rc == 0), att);
+    }
+    else
+    {
+        object->unlock();
+
+        failure_response(AUTHORIZATION, att);
+    }
 
     return;
 }
@@ -63,10 +72,11 @@ void RequestManagerUnlock::request_execute(xmlrpc_c::paramList const& paramList,
                                          RequestAttributes& att)
 {
     int     oid     = xmlrpc_c::value_int(paramList.getInt(1));
-    string  owner   = xmlrpc_c::value_string(paramList.getString(2));
 
     PoolObjectSQL * object;
     string          error_str;
+    int owner = att.uid;
+    int req_id = att.req_id;
 
     if ( basic_authorization(oid, att) == false )
     {
@@ -82,7 +92,7 @@ void RequestManagerUnlock::request_execute(xmlrpc_c::paramList const& paramList,
         return;
     }
 
-    unlock_db(object, owner);
+    unlock_db(object, owner, req_id);
 
     pool->update(object);
 
diff --git a/src/rm/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc
index 7fc800a774..1880c8d303 100644
--- a/src/rm/RequestManagerVirtualMachine.cc
+++ b/src/rm/RequestManagerVirtualMachine.cc
@@ -69,7 +69,7 @@ bool RequestManagerVirtualMachine::vm_authorization(
     {
         string t_xml;
 
-        ar.add_create_auth(att.uid, att.gid, PoolObjectSQL::IMAGE, 
+        ar.add_create_auth(att.uid, att.gid, PoolObjectSQL::IMAGE,
                 tmpl->to_xml(t_xml));
     }
 
diff --git a/src/sunstone/models/OpenNebulaJSON/ImageJSON.rb b/src/sunstone/models/OpenNebulaJSON/ImageJSON.rb
index 46f94dff55..b1e2e99d80 100644
--- a/src/sunstone/models/OpenNebulaJSON/ImageJSON.rb
+++ b/src/sunstone/models/OpenNebulaJSON/ImageJSON.rb
@@ -63,6 +63,8 @@ module OpenNebulaJSON
                  when "snapshot_flatten"    then self.snapshot_flatten(action_hash['params'])
                  when "snapshot_revert"     then self.snapshot_revert(action_hash['params'])
                  when "snapshot_delete"     then self.snapshot_delete(action_hash['params'])
+                 when "lock"         then self.lock(action_hash['params'])
+                 when "unlock"       then self.unlock(action_hash['params'])
                  else
                      error_msg = "#{action_hash['perform']} action not " <<
                          " available for this resource"
@@ -135,5 +137,13 @@ module OpenNebulaJSON
         def snapshot_delete(params=Hash.new)
             super(params['snapshot_id'].to_i)
         end
+
+        def lock(params=Hash.new)
+            super(params['level'].to_i)
+        end
+
+        def unlock(params=Hash.new)
+            super()
+        end
     end
 end
diff --git a/src/sunstone/models/OpenNebulaJSON/MarketPlaceAppJSON.rb b/src/sunstone/models/OpenNebulaJSON/MarketPlaceAppJSON.rb
index 0a24bd9e38..7584355a1c 100644
--- a/src/sunstone/models/OpenNebulaJSON/MarketPlaceAppJSON.rb
+++ b/src/sunstone/models/OpenNebulaJSON/MarketPlaceAppJSON.rb
@@ -54,6 +54,8 @@ module OpenNebulaJSON
                  when "rename"        then self.rename(action_hash['params'])
                  when "disable"       then self.disable
                  when "enable"        then self.enable
+                 when "lock"         then self.lock(action_hash['params'])
+                 when "unlock"       then self.unlock(action_hash['params'])
                  else
                      error_msg = "#{action_hash['perform']} action not " <<
                          " available for this resource"
@@ -122,5 +124,13 @@ module OpenNebulaJSON
         def rename(params=Hash.new)
             super(params['name'])
         end
+
+        def lock(params=Hash.new)
+            super(params['level'].to_i)
+        end
+
+        def unlock(params=Hash.new)
+            super()
+        end
     end
 end
diff --git a/src/sunstone/models/OpenNebulaJSON/TemplateJSON.rb b/src/sunstone/models/OpenNebulaJSON/TemplateJSON.rb
index 85a1fdd733..6c2c9f660b 100644
--- a/src/sunstone/models/OpenNebulaJSON/TemplateJSON.rb
+++ b/src/sunstone/models/OpenNebulaJSON/TemplateJSON.rb
@@ -51,6 +51,8 @@ module OpenNebulaJSON
                  when "clone"       then self.clone(action_hash['params'])
                  when "rename"      then self.rename(action_hash['params'])
                  when "delete_recursive" then self.delete_recursive(action_hash['params'])
+                 when "lock"       then self.lock(action_hash['params'])
+                 when "unlock"       then self.unlock(action_hash['params'])
                  else
                      error_msg = "#{action_hash['perform']} action not " <<
                          " available for this resource"
@@ -140,5 +142,13 @@ module OpenNebulaJSON
             recursive = (params['recursive'] == true)
             self.delete(recursive)
         end
+
+        def lock(params=Hash.new)
+            super(params['level'].to_i)
+        end
+
+        def unlock(params=Hash.new)
+            super()
+        end
     end
 end
diff --git a/src/sunstone/models/OpenNebulaJSON/VMGroupJSON.rb b/src/sunstone/models/OpenNebulaJSON/VMGroupJSON.rb
index 332312f542..841e726241 100644
--- a/src/sunstone/models/OpenNebulaJSON/VMGroupJSON.rb
+++ b/src/sunstone/models/OpenNebulaJSON/VMGroupJSON.rb
@@ -47,6 +47,8 @@ module OpenNebulaJSON
                  when "chmod"        then self.chmod_octet(action_hash['params'])
                  when "update"       then self.update(action_hash['params'])
                  when "rename"       then self.rename(action_hash['params'])
+                 when "lock"         then self.lock(action_hash['params'])
+                 when "unlock"       then self.unlock(action_hash['params'])
                  else
                      error_msg = "#{action_hash['perform']} action not " <<
                          " available for this resource"
@@ -77,5 +79,13 @@ module OpenNebulaJSON
         def rename(params=Hash.new)
             super(params['name'])
         end
+
+        def lock(params=Hash.new)
+            super(params['level'].to_i)
+        end
+
+        def unlock(params=Hash.new)
+            super()
+        end
     end
 end
diff --git a/src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb b/src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb
index 13ee9a99b5..aeee8750ed 100644
--- a/src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb
+++ b/src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb
@@ -77,6 +77,8 @@ module OpenNebulaJSON
                  when "recover"      then self.recover(action_hash['params'])
                  when "save_as_template" then self.save_as_template(action_hash['params'])
                  when "disk_resize"  then self.disk_resize(action_hash['params'])
+                 when "lock"         then self.lock(action_hash['params'])
+                 when "unlock"       then self.unlock(action_hash['params'])
                  else
                      error_msg = "#{action_hash['perform']} action not " <<
                          " available for this resource"
@@ -191,6 +193,14 @@ module OpenNebulaJSON
             super(params['name'])
         end
 
+        def lock(params=Hash.new)
+            super(params['level'].to_i)
+        end
+
+        def unlock(params=Hash.new)
+            super()
+        end
+
         def recover(params=Hash.new)
             super(params['result'].to_i)
         end
diff --git a/src/sunstone/models/OpenNebulaJSON/VirtualNetworkJSON.rb b/src/sunstone/models/OpenNebulaJSON/VirtualNetworkJSON.rb
index 3104c45385..fadbd6250d 100644
--- a/src/sunstone/models/OpenNebulaJSON/VirtualNetworkJSON.rb
+++ b/src/sunstone/models/OpenNebulaJSON/VirtualNetworkJSON.rb
@@ -54,6 +54,8 @@ module OpenNebulaJSON
                  when "add_ar"    then self.add_ar(action_hash['params'])
                  when "update_ar" then self.update_ar(action_hash['params'])
                  when "reserve"   then self.reserve(action_hash['params'])
+                 when "lock"         then self.lock(action_hash['params'])
+                 when "unlock"       then self.unlock(action_hash['params'])
                  else
                      error_msg = "#{action_hash['perform']} action not " <<
                                 " available for this resource"
@@ -111,5 +113,13 @@ module OpenNebulaJSON
             super(params['name'], params['size'], params['ar_id'],
                 params['addr'], params['vnet'])
         end
+
+        def lock(params=Hash.new)
+            super(params['level'].to_i)
+        end
+
+        def unlock(params=Hash.new)
+            super()
+        end
     end
 end
diff --git a/src/sunstone/models/OpenNebulaJSON/VirtualRouterJSON.rb b/src/sunstone/models/OpenNebulaJSON/VirtualRouterJSON.rb
index c807b1ec98..76f32a6b63 100644
--- a/src/sunstone/models/OpenNebulaJSON/VirtualRouterJSON.rb
+++ b/src/sunstone/models/OpenNebulaJSON/VirtualRouterJSON.rb
@@ -51,6 +51,8 @@ module OpenNebulaJSON
                  when "rename"      then self.rename(action_hash['params'])
                  when "attachnic"   then self.nic_attach(action_hash['params'])
                  when "detachnic"   then self.nic_detach(action_hash['params'])
+                 when "lock"         then self.lock(action_hash['params'])
+                 when "unlock"       then self.unlock(action_hash['params'])
                  else
                      error_msg = "#{action_hash['perform']} action not " <<
                          " available for this resource"
@@ -113,5 +115,13 @@ module OpenNebulaJSON
         def nic_detach(params=Hash.new)
             super(params['nic_id'].to_i)
         end
+
+        def lock(params=Hash.new)
+            super(params['level'].to_i)
+        end
+
+        def unlock(params=Hash.new)
+            super()
+        end
     end
 end
diff --git a/src/sunstone/public/app/opennebula/action.js b/src/sunstone/public/app/opennebula/action.js
index 39decd0046..e9fa1b6464 100644
--- a/src/sunstone/public/app/opennebula/action.js
+++ b/src/sunstone/public/app/opennebula/action.js
@@ -291,6 +291,13 @@ define(function(require) {
       _simple_action(params, resource, "chown", action_obj, path);
     },
 
+    "lock": function(params, resource, path) {
+      var level = params.data.extra_param;
+      var action_obj = {"level": level};
+
+      _simple_action(params, resource, "lock", action_obj, path);
+    },
+
     "chgrp": function(params, resource, path) {
       var id = params.data.extra_param;
       var action_obj = {"owner_id": "-1",
diff --git a/src/sunstone/public/app/opennebula/image.js b/src/sunstone/public/app/opennebula/image.js
index 3ea69218e6..6d31270758 100644
--- a/src/sunstone/public/app/opennebula/image.js
+++ b/src/sunstone/public/app/opennebula/image.js
@@ -164,6 +164,12 @@ define(function(require) {
     },
     "getName": function(id){
       return OpenNebulaAction.getName(id, RESOURCE);
+    },
+    "lock" : function(params) {
+      OpenNebulaAction.lock(params, RESOURCE);
+    },
+    "unlock" : function(params) {
+      OpenNebulaAction.simple_action(params, RESOURCE, "unlock");
     }
   }
 
diff --git a/src/sunstone/public/app/opennebula/marketplaceapp.js b/src/sunstone/public/app/opennebula/marketplaceapp.js
index db854ab5a6..dbdb928159 100644
--- a/src/sunstone/public/app/opennebula/marketplaceapp.js
+++ b/src/sunstone/public/app/opennebula/marketplaceapp.js
@@ -109,6 +109,12 @@ define(function(require) {
     },
     "getName": function(id){
       return OpenNebulaAction.getName(id, RESOURCE);
+    },
+    "lock" : function(params) {
+      OpenNebulaAction.lock(params, RESOURCE);
+    },
+    "unlock" : function(params) {
+      OpenNebulaAction.simple_action(params, RESOURCE, "unlock");
     }
   }
 
diff --git a/src/sunstone/public/app/opennebula/network.js b/src/sunstone/public/app/opennebula/network.js
index 9a5f7c6868..39b42ae6b0 100644
--- a/src/sunstone/public/app/opennebula/network.js
+++ b/src/sunstone/public/app/opennebula/network.js
@@ -90,7 +90,13 @@ define(function(require) {
     },
     "getName": function(id){
       return OpenNebulaAction.getName(id, RESOURCE);
-    }
+    },
+    "lock" : function(params) {
+      OpenNebulaAction.lock(params, RESOURCE);
+    },
+    "unlock" : function(params) {
+      OpenNebulaAction.simple_action(params, RESOURCE, "unlock");
+    },
   }
 
   return Network;
diff --git a/src/sunstone/public/app/opennebula/template.js b/src/sunstone/public/app/opennebula/template.js
index e033d5e0a2..3f8fe0c5f9 100644
--- a/src/sunstone/public/app/opennebula/template.js
+++ b/src/sunstone/public/app/opennebula/template.js
@@ -97,6 +97,12 @@ define(function(require) {
         return true;
       }
     },
+    "lock" : function(params) {
+      OpenNebulaAction.lock(params, RESOURCE);
+    },
+    "unlock" : function(params) {
+      OpenNebulaAction.simple_action(params, RESOURCE, "unlock");
+    },
     "cost": function(template) {
       var cost = 0;
       var capacity = template.VMTEMPLATE.TEMPLATE;
diff --git a/src/sunstone/public/app/opennebula/virtualrouter.js b/src/sunstone/public/app/opennebula/virtualrouter.js
index a44e37d873..5fe433e3ee 100644
--- a/src/sunstone/public/app/opennebula/virtualrouter.js
+++ b/src/sunstone/public/app/opennebula/virtualrouter.js
@@ -70,6 +70,12 @@ define(function(require) {
     },
     "getName": function(id){
       return OpenNebulaAction.getName(id, RESOURCE);
+    },
+    "lock" : function(params) {
+      OpenNebulaAction.lock(params, RESOURCE);
+    },
+    "unlock" : function(params) {
+      OpenNebulaAction.simple_action(params, RESOURCE, "unlock");
     }
   };
 
diff --git a/src/sunstone/public/app/opennebula/vm.js b/src/sunstone/public/app/opennebula/vm.js
index ab03a098f8..5b01a885d0 100644
--- a/src/sunstone/public/app/opennebula/vm.js
+++ b/src/sunstone/public/app/opennebula/vm.js
@@ -563,6 +563,12 @@ define(function(require) {
       var action_obj = params.data.extra_param;
       OpenNebulaAction.simple_action(params, RESOURCE, "save_as_template", action_obj);
     },
+    "lock" : function(params) {
+      OpenNebulaAction.lock(params, RESOURCE);
+    },
+    "unlock" : function(params) {
+      OpenNebulaAction.simple_action(params, RESOURCE, "unlock");
+    },
     "stateStr": function(stateId) {
       return STATES_STR[stateId];
     },
diff --git a/src/sunstone/public/app/opennebula/vmgroup.js b/src/sunstone/public/app/opennebula/vmgroup.js
index 3943cb00fc..c7c91378b1 100644
--- a/src/sunstone/public/app/opennebula/vmgroup.js
+++ b/src/sunstone/public/app/opennebula/vmgroup.js
@@ -50,6 +50,12 @@ define(function(require) {
     },
     "getName": function(id){
       return OpenNebulaAction.getName(id, RESOURCE);
+    },
+    "lock" : function(params) {
+      OpenNebulaAction.lock(params, RESOURCE);
+    },
+    "unlock" : function(params) {
+      OpenNebulaAction.simple_action(params, RESOURCE, "unlock");
     }
   };
 
diff --git a/src/sunstone/public/app/sunstone.js b/src/sunstone/public/app/sunstone.js
index ee74b28760..0d7100ee70 100644
--- a/src/sunstone/public/app/sunstone.js
+++ b/src/sunstone/public/app/sunstone.js
@@ -269,6 +269,7 @@ define(function(require) {
         }
 
         var type = button.type + "_button";
+        var data = "";
         var strClass = [type];
         switch (button.type) {
         case "select":
@@ -292,6 +293,10 @@ define(function(require) {
           strClass.push(button.custom_classes);
         }
 
+        if (button.data) {
+          data = button.data;
+        }
+
         var buttonContext;
         var text;
         switch (button.layout) {
@@ -330,6 +335,11 @@ define(function(require) {
           strClass.push("button");
           buttonCode = "<button class=\"" + strClass.join(" ") + "\" href=\"" + buttonName + "\">" + text + "</button>";
           break;
+        case "lock_buttons":
+          buttonContext = $("#" + customId + "lock_buttons", buttonsRow);
+          text = button.text;
+          buttonCode = "<li><a class=\"" + strClass.join(" ") + "\" href=\"" + buttonName + "\" data=\"" + data + "\">" + text + "</a></li>";
+          break;
         case "vmspause_buttons":
           buttonContext = $("#" + customId + "vmspause_buttons", buttonsRow);
           text = button.text;
@@ -416,8 +426,8 @@ define(function(require) {
         $("button[data-toggle=" + customId + "vmsstop_buttons]", actionBlock).remove();
       }
 
-      if ($("#" + customId + "vmspause_buttons li", actionBlock).length == 0) {
-        $("button[data-toggle=" + customId + "vmspause_buttons]", actionBlock).remove();
+      if ($("#" + customId + "lock_buttons li", actionBlock).length == 0) {
+        $("button[data-toggle=" + customId + "lock_buttons]", actionBlock).remove();
       }
 
       if ($("#" + customId + "vmsrepeat_buttons li", actionBlock).length == 0) {
@@ -459,6 +469,7 @@ define(function(require) {
     $(document).on("click", ".action_button", function() {
       var error = 0;
       var value = $(this).val();
+      var data = ($(this).attr("data") == "")? undefined: $(this).attr("data");
       if ($.isEmptyObject(value)) {
         value = $(this).attr("href");
       }
@@ -474,10 +485,10 @@ define(function(require) {
       case "multiple": //find the datatable
         var context = $(this).parents(".tab");
         var nodes = action.elements();
-        error = _runAction(value, nodes);
+        error = _runAction(value, nodes, data);
         break;
       default:
-        error = _runAction(value);
+        error = _runAction(value,undefined, data);
       }
 
       return false;
diff --git a/src/sunstone/public/app/sunstone/buttons.hbs b/src/sunstone/public/app/sunstone/buttons.hbs
index a7852d74e5..29f55e68e3 100644
--- a/src/sunstone/public/app/sunstone/buttons.hbs
+++ b/src/sunstone/public/app/sunstone/buttons.hbs
@@ -39,6 +39,12 @@
 
     <span id="{{customId}}vmsplay_buttons" class='only-sunstone-info only-sunstone-list'></span>
 
+    <button type='button' data-toggle='{{customId}}lock_buttons' class='lock-sunstone-info only-sunstone-info only-sunstone-list top_button  button secondary dropdown'>
+      <i class='fa fa-lock'/>
+    </button>
+    <ul id='{{customId}}lock_buttons' class='lock-sunstone-info only-sunstone-info only-sunstone-list dropdown-pane menu vertical' data-dropdown></ul>
+
+
     <button type='button' data-toggle='{{customId}}vmspause_buttons' class='only-sunstone-info only-sunstone-list top_button  button secondary dropdown'>
       <i class='fa fa-pause'/>
     </button>
diff --git a/src/sunstone/public/app/sunstone/tab.hbs b/src/sunstone/public/app/sunstone/tab.hbs
index 319b8a0d8b..8ee7c1989a 100644
--- a/src/sunstone/public/app/sunstone/tab.hbs
+++ b/src/sunstone/public/app/sunstone/tab.hbs
@@ -22,9 +22,12 @@
       </h5>
       <h5 class="header-title only-sunstone-info" hidden>
         <span class="header-resource">
-          {{{infoHeader}}} 
-          <small class="resource-id"></small> 
-          <small class="resource-info-header"></small> 
+          {{#if lockable }}
+          <small class="resource-lock-header-small"></small>
+          {{/if}}
+          {{{infoHeader}}}
+          <small class="resource-id"></small>
+          <small class="resource-info-header"></small>
           <small class="resource-info-header-small"></small>
         </span>
       </h5>
diff --git a/src/sunstone/public/app/tabs/acls-tab.js b/src/sunstone/public/app/tabs/acls-tab.js
index 455c3a3173..60e0d7eeff 100644
--- a/src/sunstone/public/app/tabs/acls-tab.js
+++ b/src/sunstone/public/app/tabs/acls-tab.js
@@ -40,6 +40,7 @@ define(function(require) {
     tabClass: "subTab",
     parentTab: "system-top-tab",
     listHeader: Locale.tr("Access Control Lists"),
+    lockable: false,
     subheader: '<span>\
         <span class="total_acl"/> <small>'+Locale.tr("TOTAL")+'</small>\
       </span>',
diff --git a/src/sunstone/public/app/tabs/clusters-tab.js b/src/sunstone/public/app/tabs/clusters-tab.js
index 5881903b40..90965c3dd9 100644
--- a/src/sunstone/public/app/tabs/clusters-tab.js
+++ b/src/sunstone/public/app/tabs/clusters-tab.js
@@ -49,6 +49,7 @@ define(function(require) {
     parentTab: "infrastructure-top-tab",
     listHeader: Locale.tr("Clusters"),
     infoHeader: Locale.tr("Cluster"),
+    lockable: false,
     subheader: '<span>\
         <span class="total_clusters"/> <small>'+Locale.tr("TOTAL")+'</small>\
       </span>',
diff --git a/src/sunstone/public/app/tabs/datastores-tab.js b/src/sunstone/public/app/tabs/datastores-tab.js
index 2c00fa7b58..a1bb9c2acd 100644
--- a/src/sunstone/public/app/tabs/datastores-tab.js
+++ b/src/sunstone/public/app/tabs/datastores-tab.js
@@ -49,6 +49,7 @@ define(function(require) {
     parentTab: "storage-top-tab",
     listHeader: Locale.tr("Datastores"),
     infoHeader: Locale.tr("Datastore"),
+    lockable: false,
     subheader: '<span class="total_ds"/> <small>'+Locale.tr("TOTAL")+'</small>&emsp;\
         <span class="total_on"/> <small>'+Locale.tr("ON")+'</small>&emsp;\
         <span class="total_off"/> <small>'+Locale.tr("OFF")+'</small>',
diff --git a/src/sunstone/public/app/tabs/files-tab.js b/src/sunstone/public/app/tabs/files-tab.js
index 31ff1a3ffc..76eb42bc1d 100644
--- a/src/sunstone/public/app/tabs/files-tab.js
+++ b/src/sunstone/public/app/tabs/files-tab.js
@@ -45,6 +45,7 @@ define(function(require) {
     parentTab: "storage-top-tab",
     listHeader: Locale.tr("Files"),
     infoHeader: Locale.tr("File"),
+    lockable: false,
     subheader: '<span>\
         <span class="total_files"/> <small>'+Locale.tr("TOTAL")+'</small>\
       </span>',
diff --git a/src/sunstone/public/app/tabs/groups-tab.js b/src/sunstone/public/app/tabs/groups-tab.js
index 4789c22592..b31214d71e 100644
--- a/src/sunstone/public/app/tabs/groups-tab.js
+++ b/src/sunstone/public/app/tabs/groups-tab.js
@@ -52,6 +52,7 @@ define(function(require) {
     parentTab: "system-top-tab",
     listHeader: Locale.tr("Groups"),
     infoHeader: Locale.tr("Group"),
+    lockable: false,
     subheader: '<span>\
         <span class="total_groups"/> <small>'+Locale.tr("TOTAL")+'</small>\
       </span>',
diff --git a/src/sunstone/public/app/tabs/hosts-tab.js b/src/sunstone/public/app/tabs/hosts-tab.js
index d8ed07a934..fecd6655b6 100644
--- a/src/sunstone/public/app/tabs/hosts-tab.js
+++ b/src/sunstone/public/app/tabs/hosts-tab.js
@@ -54,6 +54,7 @@ define(function(require) {
     parentTab: "infrastructure-top-tab",
     listHeader: Locale.tr("Hosts"),
     infoHeader: Locale.tr("Host"),
+    lockable: false,
     subheader: '<span class="total_hosts"/> <small>' + Locale.tr("TOTAL") + '</small>&emsp;\
         <span class="on_hosts"/> <small>' + Locale.tr("ON") + '</small>&emsp;\
         <span class="off_hosts"/> <small>' + Locale.tr("OFF") + '</small>&emsp;\
diff --git a/src/sunstone/public/app/tabs/images-tab.js b/src/sunstone/public/app/tabs/images-tab.js
index c1a515f8e6..e751834525 100644
--- a/src/sunstone/public/app/tabs/images-tab.js
+++ b/src/sunstone/public/app/tabs/images-tab.js
@@ -50,6 +50,7 @@ define(function(require) {
     parentTab: "storage-top-tab",
     listHeader: Locale.tr("Images"),
     infoHeader: Locale.tr("Image"),
+    lockable: true,
     subheader: '<span class="total_images"/> <small>'+Locale.tr("TOTAL")+'</small>&emsp;\
         <span class="size_images"/> <small>'+Locale.tr("TOTAL SIZE")+'</small>',
     resource: 'Image',
diff --git a/src/sunstone/public/app/tabs/images-tab/actions.js b/src/sunstone/public/app/tabs/images-tab/actions.js
index 67b37e2a18..40d2033cab 100644
--- a/src/sunstone/public/app/tabs/images-tab/actions.js
+++ b/src/sunstone/public/app/tabs/images-tab/actions.js
@@ -64,6 +64,10 @@ define(function(require) {
     "Image.snapshot_flatten": _commonActions.singleAction("snapshot_flatten"),
     "Image.snapshot_revert": _commonActions.singleAction("snapshot_revert"),
     "Image.snapshot_delete": _commonActions.singleAction("snapshot_delete"),
+    "Image.lockM": _commonActions.multipleAction('lock'),
+    "Image.lockU": _commonActions.multipleAction('lock'),
+    "Image.lockA": _commonActions.multipleAction('lock'),
+    "Image.unlock": _commonActions.multipleAction('unlock'),
     "Image.upload_marketplace_dialog" : {
       type: "custom",
       call: function(params) {
diff --git a/src/sunstone/public/app/tabs/images-tab/buttons.js b/src/sunstone/public/app/tabs/images-tab/buttons.js
index c4f61a5787..8f8b40a58c 100644
--- a/src/sunstone/public/app/tabs/images-tab/buttons.js
+++ b/src/sunstone/public/app/tabs/images-tab/buttons.js
@@ -16,6 +16,7 @@
 
 define(function(require) {
   var Locale = require('utils/locale');
+  var Tips = require('utils/tips');
 
   var Buttons = {
     "Image.refresh" : {
@@ -83,6 +84,29 @@ define(function(require) {
     },
     "Image.edit_labels" : {
       layout: "labels",
+    },
+    "Image.lockA" : {
+      type: "action",
+      text: Locale.tr("Admin") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Admin actions")) + "</span>",
+      layout: "lock_buttons",
+      data: 3
+    },
+    "Image.lockM" : {
+      type: "action",
+      text: Locale.tr("Manage") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Manage actions")) + "</span>",
+      layout: "lock_buttons",
+      data: 2
+    },
+    "Image.lockU" : {
+      type: "action",
+      text: Locale.tr("Use") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Use actions")) + "</span>",
+      layout: "lock_buttons",
+      data: 1
+    },
+    "Image.unlock" : {
+      type: "action",
+      text: Locale.tr("Unlock") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Unlock all actions")) + "</span>",
+      layout: "lock_buttons"
     }
   }
 
diff --git a/src/sunstone/public/app/tabs/marketplaceapps-tab.js b/src/sunstone/public/app/tabs/marketplaceapps-tab.js
index 516547d8bb..35d89ddb63 100644
--- a/src/sunstone/public/app/tabs/marketplaceapps-tab.js
+++ b/src/sunstone/public/app/tabs/marketplaceapps-tab.js
@@ -52,6 +52,7 @@ define(function(require) {
     parentTab: "storage-top-tab",
     listHeader: Locale.tr("Apps"),
     infoHeader: Locale.tr("App"),
+    lockable: true,
     subheader: '<span>\
         <span class="total_apps"/> <small>'+Locale.tr("TOTAL")+'</small>\
       </span>',
diff --git a/src/sunstone/public/app/tabs/marketplaceapps-tab/actions.js b/src/sunstone/public/app/tabs/marketplaceapps-tab/actions.js
index 35a4d3ff6d..d65572d5e0 100644
--- a/src/sunstone/public/app/tabs/marketplaceapps-tab/actions.js
+++ b/src/sunstone/public/app/tabs/marketplaceapps-tab/actions.js
@@ -37,6 +37,10 @@ define(function(require) {
   var _actions = {
     "MarketPlaceApp.create" : _commonActions.create(CREATE_DIALOG_ID),
     "MarketPlaceApp.create_dialog" : _commonActions.showCreate(CREATE_DIALOG_ID),
+    "MarketPlaceApp.lockM": _commonActions.multipleAction('lock'),
+    "MarketPlaceApp.lockU": _commonActions.multipleAction('lock'),
+    "MarketPlaceApp.lockA": _commonActions.multipleAction('lock'),
+    "MarketPlaceApp.unlock": _commonActions.multipleAction('unlock'),
     "MarketPlaceApp.download_opennebula_dialog" : {
       type: "custom",
       call: function() {
diff --git a/src/sunstone/public/app/tabs/marketplaceapps-tab/buttons.js b/src/sunstone/public/app/tabs/marketplaceapps-tab/buttons.js
index f04ea48d52..5d9ba5fcf9 100644
--- a/src/sunstone/public/app/tabs/marketplaceapps-tab/buttons.js
+++ b/src/sunstone/public/app/tabs/marketplaceapps-tab/buttons.js
@@ -16,6 +16,7 @@
 
 define(function(require) {
   var Locale = require('utils/locale');
+  var Tips = require('utils/tips');
 
   var MarketPlaceAppButtons = {
     "MarketPlaceApp.refresh" : {
@@ -66,6 +67,29 @@ define(function(require) {
     },
     "MarketPlaceApp.edit_labels" : {
       layout: "labels",
+    },
+    "MarketPlaceApp.lockA" : {
+      type: "action",
+      text: Locale.tr("Admin") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Admin actions")) + "</span>",
+      layout: "lock_buttons",
+      data: 3
+    },
+    "MarketPlaceApp.lockM" : {
+      type: "action",
+      text: Locale.tr("Manage") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Manage actions")) + "</span>",
+      layout: "lock_buttons",
+      data: 2
+    },
+    "MarketPlaceApp.lockU" : {
+      type: "action",
+      text: Locale.tr("Use") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Use actions")) + "</span>",
+      layout: "lock_buttons",
+      data: 1
+    },
+    "MarketPlaceApp.unlock" : {
+      type: "action",
+      text: Locale.tr("Unlock") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Unlock all actions")) + "</span>",
+      layout: "lock_buttons"
     }
   };
 
diff --git a/src/sunstone/public/app/tabs/marketplaces-tab.js b/src/sunstone/public/app/tabs/marketplaces-tab.js
index 2feea51b4b..0389c36794 100644
--- a/src/sunstone/public/app/tabs/marketplaces-tab.js
+++ b/src/sunstone/public/app/tabs/marketplaces-tab.js
@@ -51,6 +51,7 @@ define(function(require) {
     parentTab: "storage-top-tab",
     listHeader: Locale.tr("MarketPlaces"),
     infoHeader: Locale.tr("MarketPlace"),
+    lockable: false,
     subheader: '<span>\
         <span class="total_markets"/> <small>'+Locale.tr("TOTAL")+'</small>\
       </span>',
diff --git a/src/sunstone/public/app/tabs/oneflow-services-tab.js b/src/sunstone/public/app/tabs/oneflow-services-tab.js
index 12391238ea..bb50c513d5 100644
--- a/src/sunstone/public/app/tabs/oneflow-services-tab.js
+++ b/src/sunstone/public/app/tabs/oneflow-services-tab.js
@@ -50,6 +50,7 @@ define(function(require) {
     parentTab: "instances-top-tab",
     listHeader: Locale.tr("Services"),
     infoHeader: Locale.tr("Service"),
+    lockable: false,
     subheader: '',
     content: '<div class="row oneflow_services_error_message" hidden>\
         <div class="small-6 columns small-centered text-center">\
diff --git a/src/sunstone/public/app/tabs/oneflow-templates-tab.js b/src/sunstone/public/app/tabs/oneflow-templates-tab.js
index 40c89d1f78..d20933629f 100644
--- a/src/sunstone/public/app/tabs/oneflow-templates-tab.js
+++ b/src/sunstone/public/app/tabs/oneflow-templates-tab.js
@@ -51,6 +51,7 @@ define(function(require) {
     parentTab: "templates-top-tab",
     listHeader: Locale.tr("Service Templates"),
     infoHeader: Locale.tr("Service Template"),
+    lockable: false,
     subheader: '',
     content: '<div class="row oneflow_templates_error_message" hidden>\
         <div class="small-6 columns small-centered text-center">\
diff --git a/src/sunstone/public/app/tabs/secgroups-tab.js b/src/sunstone/public/app/tabs/secgroups-tab.js
index a444671faf..d53ac0d78a 100644
--- a/src/sunstone/public/app/tabs/secgroups-tab.js
+++ b/src/sunstone/public/app/tabs/secgroups-tab.js
@@ -48,6 +48,7 @@ define(function(require) {
     parentTab: "network-top-tab",
     listHeader: Locale.tr("Security Groups"),
     infoHeader: Locale.tr("Security Group"),
+    lockable: false,
     subheader: '<span>\
         <span class="total_secgroups"/> <small>'+Locale.tr("TOTAL")+'</small>\
       </span>',
diff --git a/src/sunstone/public/app/tabs/templates-tab.js b/src/sunstone/public/app/tabs/templates-tab.js
index ddc37667de..e0ded27fad 100644
--- a/src/sunstone/public/app/tabs/templates-tab.js
+++ b/src/sunstone/public/app/tabs/templates-tab.js
@@ -50,6 +50,7 @@ define(function(require) {
     parentTab: "templates-top-tab",
     listHeader: Locale.tr("VM Templates"),
     infoHeader: Locale.tr("VM Template"),
+    lockable: true,
     subheader: '<span>\
         <span class="total_templates"/> <small>'+Locale.tr("TOTAL")+'</small>\
       </span>',
diff --git a/src/sunstone/public/app/tabs/templates-tab/actions-common.js b/src/sunstone/public/app/tabs/templates-tab/actions-common.js
index 9259448321..650b759a40 100644
--- a/src/sunstone/public/app/tabs/templates-tab/actions-common.js
+++ b/src/sunstone/public/app/tabs/templates-tab/actions-common.js
@@ -45,7 +45,7 @@ define(function(require) {
       _actions[resource+".show"] =  _commonActions.show(),
       _actions[resource+".refresh"] =  _commonActions.refresh(),
       _actions[resource+".delete"] =  _commonActions.del(),
-      
+
       _actions[resource+".delete_dialog"] =
         {
           type: "custom",
@@ -250,9 +250,13 @@ define(function(require) {
         },
         error: Notifier.onError,
         notify: true
-      }
+      },
+      _actions[resource+".lockA"] =  _commonActions.multipleAction("lock"),
+      _actions[resource+".lockM"] =  _commonActions.multipleAction("lock"),
+      _actions[resource+".lockU"] =  _commonActions.multipleAction("lock"),
+      _actions[resource+".unlock"] =  _commonActions.multipleAction("unlock")
+
 
-  
     return _actions;
   }
 
diff --git a/src/sunstone/public/app/tabs/templates-tab/buttons.js b/src/sunstone/public/app/tabs/templates-tab/buttons.js
index ed7831e3bd..bad31000c5 100644
--- a/src/sunstone/public/app/tabs/templates-tab/buttons.js
+++ b/src/sunstone/public/app/tabs/templates-tab/buttons.js
@@ -16,6 +16,7 @@
 
 define(function(require) {
   var Locale = require('utils/locale');
+  var Tips = require('utils/tips');
 
   var Buttons = {
     "Template.refresh" : {
@@ -82,6 +83,29 @@ define(function(require) {
     },
     "Template.edit_labels" : {
       layout: "labels",
+    },
+    "Template.lockA" : {
+      type: "action",
+      text: Locale.tr("Admin") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Admin actions")) + "</span>",
+      layout: "lock_buttons",
+      data: 3
+    },
+    "Template.lockM" : {
+      type: "action",
+      text: Locale.tr("Manage") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Manage actions")) + "</span>",
+      layout: "lock_buttons",
+      data: 2
+    },
+    "Template.lockU" : {
+      type: "action",
+      text: Locale.tr("Use") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Use actions")) + "</span>",
+      layout: "lock_buttons",
+      data: 1
+    },
+    "Template.unlock" : {
+      type: "action",
+      text: Locale.tr("Unlock") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Unlock all actions")) + "</span>",
+      layout: "lock_buttons"
     }
   };
 
diff --git a/src/sunstone/public/app/tabs/users-tab.js b/src/sunstone/public/app/tabs/users-tab.js
index 5dbea857a3..e16e823476 100644
--- a/src/sunstone/public/app/tabs/users-tab.js
+++ b/src/sunstone/public/app/tabs/users-tab.js
@@ -56,6 +56,7 @@ define(function(require) {
     parentTab: "system-top-tab",
     listHeader: Locale.tr("Users"),
     infoHeader: Locale.tr("User"),
+    lockable: false,
     subheader: '<span>\
         <span class="total_users"/> <small>'+Locale.tr("TOTAL")+'</small>\
       </span>',
diff --git a/src/sunstone/public/app/tabs/vdcs-tab.js b/src/sunstone/public/app/tabs/vdcs-tab.js
index 8fcbe3c35c..4453556012 100644
--- a/src/sunstone/public/app/tabs/vdcs-tab.js
+++ b/src/sunstone/public/app/tabs/vdcs-tab.js
@@ -48,6 +48,7 @@ define(function(require) {
     parentTab: "system-top-tab",
     listHeader: Locale.tr("Virtual Data Centers"),
     infoHeader: Locale.tr("Virtual Data Center"),
+    lockable: false,
     subheader: '<span>\
         <span class="total_vdcs"/> <small>'+Locale.tr("TOTAL")+'</small>\
       </span>',
diff --git a/src/sunstone/public/app/tabs/vmgroup-tab.js b/src/sunstone/public/app/tabs/vmgroup-tab.js
index 926ac408a3..0d49e26028 100644
--- a/src/sunstone/public/app/tabs/vmgroup-tab.js
+++ b/src/sunstone/public/app/tabs/vmgroup-tab.js
@@ -40,6 +40,7 @@ define(function(require) {
     parentTab: "templates-top-tab",
     listHeader: Locale.tr("VM Groups"),
     infoHeader: Locale.tr("VM Groups"),
+    lockable: true,
     subheader: '<span>\
         <span class="total_vmgroup"/> <small>'+Locale.tr("TOTAL")+'</small>\
         </small>&emsp;\
diff --git a/src/sunstone/public/app/tabs/vmgroup-tab/actions.js b/src/sunstone/public/app/tabs/vmgroup-tab/actions.js
index f6965cbcde..e004e6e366 100644
--- a/src/sunstone/public/app/tabs/vmgroup-tab/actions.js
+++ b/src/sunstone/public/app/tabs/vmgroup-tab/actions.js
@@ -46,7 +46,11 @@ define(function(require) {
     "VMGroup.append_template" : _commonActions.appendTemplate(),
     "VMGroup.chown": _commonActions.multipleAction('chown'),
     "VMGroup.chgrp": _commonActions.multipleAction('chgrp'),
-    "VMGroup.chmod": _commonActions.singleAction('chmod')
+    "VMGroup.chmod": _commonActions.singleAction('chmod'),
+    "VMGroup.lockM": _commonActions.multipleAction('lock'),
+    "VMGroup.lockU": _commonActions.multipleAction('lock'),
+    "VMGroup.lockA": _commonActions.multipleAction('lock'),
+    "VMGroup.unlock": _commonActions.multipleAction('unlock')
   };
 
   return _actions;
diff --git a/src/sunstone/public/app/tabs/vmgroup-tab/buttons.js b/src/sunstone/public/app/tabs/vmgroup-tab/buttons.js
index dc4933d710..7414111f14 100644
--- a/src/sunstone/public/app/tabs/vmgroup-tab/buttons.js
+++ b/src/sunstone/public/app/tabs/vmgroup-tab/buttons.js
@@ -17,6 +17,7 @@
 define(function(require) {
   var Locale = require('utils/locale');
   var TemplateButtons = require('tabs/templates-tab/buttons');
+  var Tips = require('utils/tips');
 
   var Buttons = {
     "VMGroup.refresh" : {
@@ -51,6 +52,29 @@ define(function(require) {
       type: "confirm",
       text: Locale.tr("Delete"),
       layout: "del"
+    },
+    "VMGroup.lockA" : {
+      type: "action",
+      text: Locale.tr("Admin") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Admin actions")) + "</span>",
+      layout: "lock_buttons",
+      data: 3
+    },
+    "VMGroup.lockM" : {
+      type: "action",
+      text: Locale.tr("Manage") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Manage actions")) + "</span>",
+      layout: "lock_buttons",
+      data: 2
+    },
+    "VMGroup.lockU" : {
+      type: "action",
+      text: Locale.tr("Use") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Use actions")) + "</span>",
+      layout: "lock_buttons",
+      data: 1
+    },
+    "VMGroup.unlock" : {
+      type: "action",
+      text: Locale.tr("Unlock") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Unlock all actions")) + "</span>",
+      layout: "lock_buttons"
     }/*,
     "VMGroup.edit_labels" : {
       layout: "labels",
diff --git a/src/sunstone/public/app/tabs/vms-tab.js b/src/sunstone/public/app/tabs/vms-tab.js
index 423e318ae6..ae247d9c7f 100644
--- a/src/sunstone/public/app/tabs/vms-tab.js
+++ b/src/sunstone/public/app/tabs/vms-tab.js
@@ -70,6 +70,7 @@ define(function(require) {
     parentTab: "instances-top-tab",
     listHeader: Locale.tr("VMs"),
     infoHeader: Locale.tr("VM"),
+    lockable: true,
     subheader: '<span class="total_vms"/> <small>' + Locale.tr("TOTAL") + '</small>&emsp;\
         <span class="active_vms"/> <small>' + Locale.tr("ACTIVE") + '</small>&emsp;\
         <span class="off_vms"/> <small>' + Locale.tr("OFF") + '</small>&emsp;\
diff --git a/src/sunstone/public/app/tabs/vms-tab/actions.js b/src/sunstone/public/app/tabs/vms-tab/actions.js
index 38d65c32cd..b0763043a3 100644
--- a/src/sunstone/public/app/tabs/vms-tab/actions.js
+++ b/src/sunstone/public/app/tabs/vms-tab/actions.js
@@ -75,6 +75,10 @@ define(function(require) {
     "VM.recover": _commonActions.multipleAction('recover'),
     "VM.resched": _commonActions.multipleAction('resched'),
     "VM.unresched": _commonActions.multipleAction('unresched'),
+    "VM.lockM": _commonActions.multipleAction('lock'),
+    "VM.lockU": _commonActions.multipleAction('lock'),
+    "VM.lockA": _commonActions.multipleAction('lock'),
+    "VM.unlock": _commonActions.multipleAction('unlock'),
 
     "VM.chmod": _commonActions.singleAction('chmod'),
     "VM.rename": _commonActions.singleAction('rename'),
diff --git a/src/sunstone/public/app/tabs/vms-tab/buttons.js b/src/sunstone/public/app/tabs/vms-tab/buttons.js
index f578e902d0..912bb8c5b2 100644
--- a/src/sunstone/public/app/tabs/vms-tab/buttons.js
+++ b/src/sunstone/public/app/tabs/vms-tab/buttons.js
@@ -197,6 +197,29 @@ define(function(require) {
     },
     "VM.edit_labels" : {
       layout: "labels",
+    },
+    "VM.lockA" : {
+      type: "action",
+      text: Locale.tr("Admin") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Admin actions")) + "</span>",
+      layout: "lock_buttons",
+      data: 3
+    },
+    "VM.lockM" : {
+      type: "action",
+      text: Locale.tr("Manage") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Manage actions")) + "</span>",
+      layout: "lock_buttons",
+      data: 2
+    },
+    "VM.lockU" : {
+      type: "action",
+      text: Locale.tr("Use") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Use actions")) + "</span>",
+      layout: "lock_buttons",
+      data: 1
+    },
+    "VM.unlock" : {
+      type: "action",
+      text: Locale.tr("Unlock") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Unlock all actions")) + "</span>",
+      layout: "lock_buttons"
     }
   }
   return Buttons;
diff --git a/src/sunstone/public/app/tabs/vms-tab/hooks/header.js b/src/sunstone/public/app/tabs/vms-tab/hooks/header.js
index eca1454a82..e2a201fb6e 100644
--- a/src/sunstone/public/app/tabs/vms-tab/hooks/header.js
+++ b/src/sunstone/public/app/tabs/vms-tab/hooks/header.js
@@ -20,6 +20,8 @@ define(function(require) {
    */
 
   var OpenNebulaVM = require('opennebula/vm');
+  var Locale = require('utils/locale');
+  var Humanize = require('utils/humanize');
 
   /*
     CONSTANTS
@@ -45,6 +47,13 @@ define(function(require) {
 
     $('.resource-info-header', '#' + TAB_ID).text(element.NAME);
     $('.resource-info-header-small', '#' + TAB_ID).text(state);
+
+    if (element.LOCK){
+      $('.resource-lock-header-small', '#' + TAB_ID).html("<i class='header-title fa fa-lock'> "+Locale.tr(Humanize.lock_to_str(element.LOCK.LOCKED))+"</i>");
+      $('.resource-lock-header-small', '#' + TAB_ID).show();
+    } else {
+      $('.resource-lock-header-small', '#' + TAB_ID).hide();
+    }
   }
 
   function _post(info, contextTabId) {
diff --git a/src/sunstone/public/app/tabs/vnets-tab.js b/src/sunstone/public/app/tabs/vnets-tab.js
index 40e24b26af..426d53aedb 100644
--- a/src/sunstone/public/app/tabs/vnets-tab.js
+++ b/src/sunstone/public/app/tabs/vnets-tab.js
@@ -55,6 +55,7 @@ define(function(require) {
     parentTab: "network-top-tab",
     listHeader: Locale.tr("Virtual Networks"),
     infoHeader: Locale.tr("Virtual Network"),
+    lockable: true,
     subheader: '<span class="total_vnets"/> <small>'+Locale.tr("TOTAL")+'</small>&emsp;\
         <span class="addresses_vnets"/> <small>'+Locale.tr("USED IPs")+'</small>',
     resource: 'Network',
diff --git a/src/sunstone/public/app/tabs/vnets-tab/actions.js b/src/sunstone/public/app/tabs/vnets-tab/actions.js
index 6353d2c9e8..795662d1f0 100644
--- a/src/sunstone/public/app/tabs/vnets-tab/actions.js
+++ b/src/sunstone/public/app/tabs/vnets-tab/actions.js
@@ -55,6 +55,10 @@ define(function(require) {
     "Network.append_template" : _commonActions.appendTemplate(),
     "Network.update_dialog" : _commonActions.checkAndShowUpdate(),
     "Network.show_to_update" : _commonActions.showUpdate(CREATE_DIALOG_ID),
+    "Network.lockM": _commonActions.multipleAction('lock'),
+    "Network.lockU": _commonActions.multipleAction('lock'),
+    "Network.lockA": _commonActions.multipleAction('lock'),
+    "Network.unlock": _commonActions.multipleAction('unlock'),
 
     "Network.import_dialog" : {
       type: "custom",
diff --git a/src/sunstone/public/app/tabs/vnets-tab/buttons.js b/src/sunstone/public/app/tabs/vnets-tab/buttons.js
index 1721133d0e..db19b24136 100644
--- a/src/sunstone/public/app/tabs/vnets-tab/buttons.js
+++ b/src/sunstone/public/app/tabs/vnets-tab/buttons.js
@@ -16,6 +16,7 @@
 
 define(function(require) {
   var Locale = require('utils/locale');
+  var Tips = require('utils/tips');
 
   var VNetButtons = {
     "Network.refresh" : {
@@ -73,6 +74,29 @@ define(function(require) {
     },
     "Network.edit_labels" : {
       layout: "labels",
+    },
+    "Network.lockA" : {
+      type: "action",
+      text: Locale.tr("Admin") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Admin actions")) + "</span>",
+      layout: "lock_buttons",
+      data: 3
+    },
+    "Network.lockM" : {
+      type: "action",
+      text: Locale.tr("Manage") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Manage actions")) + "</span>",
+      layout: "lock_buttons",
+      data: 2
+    },
+    "Network.lockU" : {
+      type: "action",
+      text: Locale.tr("Use") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Use actions")) + "</span>",
+      layout: "lock_buttons",
+      data: 1
+    },
+    "Network.unlock" : {
+      type: "action",
+      text: Locale.tr("Unlock") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Unlock all actions")) + "</span>",
+      layout: "lock_buttons"
     }
   };
 
diff --git a/src/sunstone/public/app/tabs/vrouter-templates-tab.js b/src/sunstone/public/app/tabs/vrouter-templates-tab.js
index 3dbb7b2440..f8ab20bb13 100644
--- a/src/sunstone/public/app/tabs/vrouter-templates-tab.js
+++ b/src/sunstone/public/app/tabs/vrouter-templates-tab.js
@@ -48,6 +48,7 @@ define(function(require) {
     parentTab: "templates-top-tab",
     listHeader: Locale.tr("Virtual Router VM Templates"),
     infoHeader: Locale.tr("Virtual Router VM Template"),
+    lockable: true,
     subheader: '<span>\
         <span class="total_vrouters"/> <small>'+Locale.tr("TOTAL")+'</small>\
       </span>',
diff --git a/src/sunstone/public/app/tabs/vrouters-tab.js b/src/sunstone/public/app/tabs/vrouters-tab.js
index d9b4fa9236..7af6e72229 100644
--- a/src/sunstone/public/app/tabs/vrouters-tab.js
+++ b/src/sunstone/public/app/tabs/vrouters-tab.js
@@ -49,6 +49,7 @@ define(function(require) {
     parentTab: "instances-top-tab",
     listHeader: Locale.tr("Virtual Routers"),
     infoHeader: Locale.tr("Virtual Router"),
+    lockable: true,
     subheader: '<span>\
         <span class="total_routers"/> <small>'+Locale.tr("TOTAL")+'</small>\
       </span>',
diff --git a/src/sunstone/public/app/tabs/vrouters-tab/actions.js b/src/sunstone/public/app/tabs/vrouters-tab/actions.js
index 0259a89fe5..838371b9c3 100644
--- a/src/sunstone/public/app/tabs/vrouters-tab/actions.js
+++ b/src/sunstone/public/app/tabs/vrouters-tab/actions.js
@@ -34,6 +34,10 @@ define(function(require) {
   var _actions = {
     "VirtualRouter.create" : _commonActions.create(CREATE_DIALOG_ID),
     "VirtualRouter.create_dialog" : _commonActions.showCreate(CREATE_DIALOG_ID),
+    "VirtualRouter.lockM": _commonActions.multipleAction('lock'),
+    "VirtualRouter.lockU": _commonActions.multipleAction('lock'),
+    "VirtualRouter.lockA": _commonActions.multipleAction('lock'),
+    "VirtualRouter.unlock": _commonActions.multipleAction('unlock'),
     "VirtualRouter.instantiate_vms" : {
       type: "custom",
       call: function() {
diff --git a/src/sunstone/public/app/tabs/vrouters-tab/buttons.js b/src/sunstone/public/app/tabs/vrouters-tab/buttons.js
index f921277b5b..a73ed8ec77 100644
--- a/src/sunstone/public/app/tabs/vrouters-tab/buttons.js
+++ b/src/sunstone/public/app/tabs/vrouters-tab/buttons.js
@@ -16,6 +16,7 @@
 
 define(function(require) {
   var Locale = require('utils/locale');
+  var Tips = require('utils/tips');
 
   var Buttons = {
     "VirtualRouter.refresh" : {
@@ -53,6 +54,29 @@ define(function(require) {
     },
     "VirtualRouter.edit_labels" : {
       layout: "labels",
+    },
+    "VirtualRouter.lockA" : {
+      type: "action",
+      text: Locale.tr("Admin") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Admin actions")) + "</span>",
+      layout: "lock_buttons",
+      data: 3
+    },
+    "VirtualRouter.lockM" : {
+      type: "action",
+      text: Locale.tr("Manage") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Manage actions")) + "</span>",
+      layout: "lock_buttons",
+      data: 2
+    },
+    "VirtualRouter.lockU" : {
+      type: "action",
+      text: Locale.tr("Use") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Use actions")) + "</span>",
+      layout: "lock_buttons",
+      data: 1
+    },
+    "VirtualRouter.unlock" : {
+      type: "action",
+      text: Locale.tr("Unlock") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Unlock all actions")) + "</span>",
+      layout: "lock_buttons"
     }
   };
 
diff --git a/src/sunstone/public/app/tabs/zones-tab.js b/src/sunstone/public/app/tabs/zones-tab.js
index caa6895f33..3a52f3746e 100644
--- a/src/sunstone/public/app/tabs/zones-tab.js
+++ b/src/sunstone/public/app/tabs/zones-tab.js
@@ -43,6 +43,7 @@ define(function(require) {
     parentTab: "infrastructure-top-tab",
     listHeader: Locale.tr("Zones"),
     infoHeader: Locale.tr("Zone"),
+    lockable: false,
     subheader: '<span>\
         <span class="total_zones"/> <small>'+Locale.tr("TOTAL")+'</small>\
       </span>',
diff --git a/src/sunstone/public/app/utils/hooks/header.js b/src/sunstone/public/app/utils/hooks/header.js
index 83da714615..3912b25284 100644
--- a/src/sunstone/public/app/utils/hooks/header.js
+++ b/src/sunstone/public/app/utils/hooks/header.js
@@ -19,11 +19,19 @@ define(function(require) {
   /*
     FUNCTION DEFINITIONS
    */
+  var Locale = require('utils/locale');
+  var Humanize = require('utils/humanize');
 
   function _pre(info, contextTabId) {
     var element = info[Object.keys(info)[0]];
 
     $('.resource-info-header', '#' + contextTabId).text(element.NAME);
+
+    if (element.LOCK){
+      $('.resource-lock-header-small', '#' + contextTabId).html("<span data-tooltip aria-haspopup='true' class='has-tip' data-disable-hover='false' tabindex='1' title="+Locale.tr(Humanize.lock_to_str(element.LOCK.LOCKED))+"><i class='fa fa-lock fa-2x'/></span>");
+    } else {
+      $('.resource-lock-header-small', '#' + contextTabId).html("<i style='color: #cacedd;' class='fa fa-unlock-alt fa-2x'/>");
+    }
   }
 
   function _post(info, contextTabId) {
diff --git a/src/sunstone/public/app/utils/humanize.js b/src/sunstone/public/app/utils/humanize.js
index af9c21d189..cd045ccc34 100644
--- a/src/sunstone/public/app/utils/humanize.js
+++ b/src/sunstone/public/app/utils/humanize.js
@@ -34,7 +34,8 @@ define(function(require) {
     'prettyTimeAxis': _prettyTimeAxis,
     'prettyPrintJSON': _prettyPrintJSON,
     'prettyTimeAgo': _format_date,
-    'prettyTimeDatatable': _prettyTimeDatatable
+    'prettyTimeDatatable': _prettyTimeDatatable,
+    'lock_to_str': _lock_to_str
   }
 
   /*
@@ -299,7 +300,9 @@ define(function(require) {
     return difference_in_seconds;
 
     function _fourdigits(number)  {
-          return (number < 1000) ? number + 1900 : number;}
+      return (number < 1000) ? number + 1900 : number;
+    }
+
 
     //function _plural(number) {
     //  if(parseInt(number) === 1) {
@@ -308,4 +311,22 @@ define(function(require) {
     //  return "s";
     //}
   }
+  function _lock_to_str(level)  {
+    var level_str = "";
+    switch(level) {
+      case "1":
+        level_str = "Use";
+        break;
+      case "2":
+        level_str = "Manage";
+        break;
+      case "3":
+        level_str = "Admin";
+        break;
+      case "4":
+        level_str = "All";
+        break;
+    }
+    return level_str;
+  }
 })
diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc
index a493f6b7e9..2d4a213e85 100644
--- a/src/vm/VirtualMachine.cc
+++ b/src/vm/VirtualMachine.cc
@@ -1953,6 +1953,7 @@ string& VirtualMachine::to_xml_extended(string& xml, int n_history) const
     string history_xml;
     string perm_xml;
     string snap_xml;
+    string lock_str;
 
     ostringstream   oss;
 
@@ -1973,6 +1974,7 @@ string& VirtualMachine::to_xml_extended(string& xml, int n_history) const
         << "<STIME>"     << stime     << "</STIME>"
         << "<ETIME>"     << etime     << "</ETIME>"
         << "<DEPLOY_ID>" << deploy_id << "</DEPLOY_ID>"
+        << lock_db_to_xml(lock_str)
         << monitoring.to_xml(monitoring_xml)
         << obj_template->to_xml(template_xml)
         << user_obj_template->to_xml(user_template_xml);
@@ -2072,6 +2074,8 @@ int VirtualMachine::from_xml(const string &xml_str)
     prev_state     = static_cast<VmState>(istate);
     prev_lcm_state = static_cast<LcmState>(ilcmstate);
 
+    rc += lock_db_from_xml();
+
     // -------------------------------------------------------------------------
     // Virtual Machine template and attributes
     // -------------------------------------------------------------------------
diff --git a/src/vm_group/VMGroup.cc b/src/vm_group/VMGroup.cc
index b4bfe2c2d3..3eb7357fb0 100644
--- a/src/vm_group/VMGroup.cc
+++ b/src/vm_group/VMGroup.cc
@@ -63,6 +63,7 @@ string& VMGroup::to_xml(string& xml) const
     string template_xml;
     string perms_xml;
     string roles_xml;
+    string lock_str;
 
     oss <<
     "<VM_GROUP>"    <<
@@ -73,6 +74,7 @@ string& VMGroup::to_xml(string& xml) const
         "<GNAME>"   << gname    << "</GNAME>"  <<
         "<NAME>"    << name     << "</NAME>"   <<
         perms_to_xml(perms_xml)                <<
+        lock_db_to_xml(lock_str)               <<
         roles.to_xml(roles_xml)                <<
         obj_template->to_xml(template_xml)     <<
     "</VM_GROUP>";
@@ -103,6 +105,9 @@ int VMGroup::from_xml(const string &xml_str)
     // Permissions
     rc += perms_from_xml();
 
+    // Lock
+    rc += lock_db_from_xml();
+
     // Get associated template
     ObjectXML::get_nodes("/VM_GROUP/TEMPLATE", content);
 
diff --git a/src/vm_template/VMTemplate.cc b/src/vm_template/VMTemplate.cc
index 7347aba17f..45a5f6ed2b 100644
--- a/src/vm_template/VMTemplate.cc
+++ b/src/vm_template/VMTemplate.cc
@@ -208,6 +208,7 @@ string& VMTemplate::to_xml(string& xml, const Template* tmpl) const
     ostringstream   oss;
     string          template_xml;
     string          perm_str;
+    string          lock_str;
 
     oss << "<VMTEMPLATE>"
             << "<ID>"       << oid        << "</ID>"
@@ -216,6 +217,7 @@ string& VMTemplate::to_xml(string& xml, const Template* tmpl) const
             << "<UNAME>"    << uname      << "</UNAME>"
             << "<GNAME>"    << gname      << "</GNAME>"
             << "<NAME>"     << name       << "</NAME>"
+            << lock_db_to_xml(lock_str)
             << perms_to_xml(perm_str)
             << "<REGTIME>"  << regtime    << "</REGTIME>"
             << tmpl->to_xml(template_xml)
@@ -246,6 +248,7 @@ int VMTemplate::from_xml(const string& xml)
     rc += xpath(name,       "/VMTEMPLATE/NAME",    "not_found");
     rc += xpath<time_t>(regtime, "/VMTEMPLATE/REGTIME", 0);
 
+    rc += lock_db_from_xml();
     // Permissions
     rc += perms_from_xml();
 
diff --git a/src/vnm/VirtualNetwork.cc b/src/vnm/VirtualNetwork.cc
index ac51b305ed..1c6b93aa42 100644
--- a/src/vnm/VirtualNetwork.cc
+++ b/src/vnm/VirtualNetwork.cc
@@ -428,6 +428,7 @@ string& VirtualNetwork::to_xml_extended(string& xml, bool extended,
     string template_xml;
     string leases_xml;
     string perm_str;
+    string lock_str;
 
     int int_vlan_id_automatic = vlan_id_automatic ? 1 : 0;
 
@@ -439,6 +440,7 @@ string& VirtualNetwork::to_xml_extended(string& xml, bool extended,
             "<UNAME>"  << uname    << "</UNAME>" <<
             "<GNAME>"  << gname    << "</GNAME>" <<
             "<NAME>"   << name     << "</NAME>"  <<
+            lock_db_to_xml(lock_str) <<
             perms_to_xml(perm_str) <<
             Clusterable::to_xml(clusters_xml)    <<
             "<BRIDGE>" << one_util::escape_xml(bridge) << "</BRIDGE>";
@@ -518,6 +520,8 @@ int VirtualNetwork::from_xml(const string &xml_str)
     rc += xpath(name,   "/VNET/NAME",  "not_found");
     rc += xpath(bridge, "/VNET/BRIDGE","not_found");
 
+    rc += lock_db_from_xml();
+
     // Permissions
     rc += perms_from_xml();
 
diff --git a/src/vrouter/VirtualRouter.cc b/src/vrouter/VirtualRouter.cc
index a4fdd9c312..584379e2ba 100644
--- a/src/vrouter/VirtualRouter.cc
+++ b/src/vrouter/VirtualRouter.cc
@@ -307,6 +307,7 @@ string& VirtualRouter::to_xml(string& xml) const
     string          template_xml;
     string          vm_collection_xml;
     string          perm_str;
+    string          lock_str;
 
     oss << "<VROUTER>"
             << "<ID>"       << oid        << "</ID>"
@@ -316,6 +317,7 @@ string& VirtualRouter::to_xml(string& xml) const
             << "<GNAME>"    << gname      << "</GNAME>"
             << "<NAME>"     << name       << "</NAME>"
             << perms_to_xml(perm_str)
+            << lock_db_to_xml(lock_str)
             << vms.to_xml(vm_collection_xml)
             << obj_template->to_xml(template_xml)
         << "</VROUTER>";
@@ -347,6 +349,9 @@ int VirtualRouter::from_xml(const string& xml)
     // Permissions
     rc += perms_from_xml();
 
+    // Lock
+    rc += lock_db_from_xml();
+
     // Get associated classes
     rc += vms.from_xml(this, "/VROUTER/");
 

From 5399f21a8e4fe5a835853cc3f35bd821331c705a Mon Sep 17 00:00:00 2001
From: juanmont <jjmontiel@opennebula.org>
Date: Wed, 24 Jan 2018 17:04:17 +0100
Subject: [PATCH 5/6] F #1377: Resolved Bugs

---
 src/sunstone/public/app/sunstone.js                       | 4 ++++
 src/sunstone/public/app/tabs/images-tab/buttons.js        | 8 ++++----
 .../public/app/tabs/marketplaceapps-tab/buttons.js        | 8 ++++----
 src/sunstone/public/app/tabs/templates-tab/buttons.js     | 8 ++++----
 src/sunstone/public/app/tabs/vmgroup-tab/buttons.js       | 8 ++++----
 src/sunstone/public/app/tabs/vms-tab/buttons.js           | 8 ++++----
 src/sunstone/public/app/tabs/vms-tab/hooks/header.js      | 5 ++---
 src/sunstone/public/app/tabs/vnets-tab/buttons.js         | 8 ++++----
 src/sunstone/public/app/tabs/vrouters-tab/buttons.js      | 8 ++++----
 9 files changed, 34 insertions(+), 31 deletions(-)

diff --git a/src/sunstone/public/app/sunstone.js b/src/sunstone/public/app/sunstone.js
index 0d7100ee70..089795d4cc 100644
--- a/src/sunstone/public/app/sunstone.js
+++ b/src/sunstone/public/app/sunstone.js
@@ -430,6 +430,10 @@ define(function(require) {
         $("button[data-toggle=" + customId + "lock_buttons]", actionBlock).remove();
       }
 
+      if ($("#" + customId + "vmspause_buttons li", actionBlock).length == 0) {
+        $("button[data-toggle=" + customId + "vmspause_buttons]", actionBlock).remove();
+      }
+
       if ($("#" + customId + "vmsrepeat_buttons li", actionBlock).length == 0) {
         $("button[data-toggle=" + customId + "vmsrepeat_buttons]", actionBlock).remove();
       }
diff --git a/src/sunstone/public/app/tabs/images-tab/buttons.js b/src/sunstone/public/app/tabs/images-tab/buttons.js
index 8f8b40a58c..4f76f09d04 100644
--- a/src/sunstone/public/app/tabs/images-tab/buttons.js
+++ b/src/sunstone/public/app/tabs/images-tab/buttons.js
@@ -87,25 +87,25 @@ define(function(require) {
     },
     "Image.lockA" : {
       type: "action",
-      text: Locale.tr("Admin") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Admin actions")) + "</span>",
+      text: Locale.tr("Admin"),
       layout: "lock_buttons",
       data: 3
     },
     "Image.lockM" : {
       type: "action",
-      text: Locale.tr("Manage") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Manage actions")) + "</span>",
+      text: Locale.tr("Manage"),
       layout: "lock_buttons",
       data: 2
     },
     "Image.lockU" : {
       type: "action",
-      text: Locale.tr("Use") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Use actions")) + "</span>",
+      text: Locale.tr("Use"),
       layout: "lock_buttons",
       data: 1
     },
     "Image.unlock" : {
       type: "action",
-      text: Locale.tr("Unlock") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Unlock all actions")) + "</span>",
+      text: Locale.tr("Unlock"),
       layout: "lock_buttons"
     }
   }
diff --git a/src/sunstone/public/app/tabs/marketplaceapps-tab/buttons.js b/src/sunstone/public/app/tabs/marketplaceapps-tab/buttons.js
index 5d9ba5fcf9..26c2550d2b 100644
--- a/src/sunstone/public/app/tabs/marketplaceapps-tab/buttons.js
+++ b/src/sunstone/public/app/tabs/marketplaceapps-tab/buttons.js
@@ -70,25 +70,25 @@ define(function(require) {
     },
     "MarketPlaceApp.lockA" : {
       type: "action",
-      text: Locale.tr("Admin") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Admin actions")) + "</span>",
+      text: Locale.tr("Admin"),
       layout: "lock_buttons",
       data: 3
     },
     "MarketPlaceApp.lockM" : {
       type: "action",
-      text: Locale.tr("Manage") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Manage actions")) + "</span>",
+      text: Locale.tr("Manage"),
       layout: "lock_buttons",
       data: 2
     },
     "MarketPlaceApp.lockU" : {
       type: "action",
-      text: Locale.tr("Use") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Use actions")) + "</span>",
+      text: Locale.tr("Use"),
       layout: "lock_buttons",
       data: 1
     },
     "MarketPlaceApp.unlock" : {
       type: "action",
-      text: Locale.tr("Unlock") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Unlock all actions")) + "</span>",
+      text: Locale.tr("Unlock"),
       layout: "lock_buttons"
     }
   };
diff --git a/src/sunstone/public/app/tabs/templates-tab/buttons.js b/src/sunstone/public/app/tabs/templates-tab/buttons.js
index bad31000c5..718c67eed9 100644
--- a/src/sunstone/public/app/tabs/templates-tab/buttons.js
+++ b/src/sunstone/public/app/tabs/templates-tab/buttons.js
@@ -86,25 +86,25 @@ define(function(require) {
     },
     "Template.lockA" : {
       type: "action",
-      text: Locale.tr("Admin") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Admin actions")) + "</span>",
+      text: Locale.tr("Admin"),
       layout: "lock_buttons",
       data: 3
     },
     "Template.lockM" : {
       type: "action",
-      text: Locale.tr("Manage") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Manage actions")) + "</span>",
+      text: Locale.tr("Manage"),
       layout: "lock_buttons",
       data: 2
     },
     "Template.lockU" : {
       type: "action",
-      text: Locale.tr("Use") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Use actions")) + "</span>",
+      text: Locale.tr("Use"),
       layout: "lock_buttons",
       data: 1
     },
     "Template.unlock" : {
       type: "action",
-      text: Locale.tr("Unlock") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Unlock all actions")) + "</span>",
+      text: Locale.tr("Unlock"),
       layout: "lock_buttons"
     }
   };
diff --git a/src/sunstone/public/app/tabs/vmgroup-tab/buttons.js b/src/sunstone/public/app/tabs/vmgroup-tab/buttons.js
index 7414111f14..6f34fbedf8 100644
--- a/src/sunstone/public/app/tabs/vmgroup-tab/buttons.js
+++ b/src/sunstone/public/app/tabs/vmgroup-tab/buttons.js
@@ -55,25 +55,25 @@ define(function(require) {
     },
     "VMGroup.lockA" : {
       type: "action",
-      text: Locale.tr("Admin") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Admin actions")) + "</span>",
+      text: Locale.tr("Admin"),
       layout: "lock_buttons",
       data: 3
     },
     "VMGroup.lockM" : {
       type: "action",
-      text: Locale.tr("Manage") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Manage actions")) + "</span>",
+      text: Locale.tr("Manage"),
       layout: "lock_buttons",
       data: 2
     },
     "VMGroup.lockU" : {
       type: "action",
-      text: Locale.tr("Use") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Use actions")) + "</span>",
+      text: Locale.tr("Use"),
       layout: "lock_buttons",
       data: 1
     },
     "VMGroup.unlock" : {
       type: "action",
-      text: Locale.tr("Unlock") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Unlock all actions")) + "</span>",
+      text: Locale.tr("Unlock"),
       layout: "lock_buttons"
     }/*,
     "VMGroup.edit_labels" : {
diff --git a/src/sunstone/public/app/tabs/vms-tab/buttons.js b/src/sunstone/public/app/tabs/vms-tab/buttons.js
index 912bb8c5b2..34a0aa07ca 100644
--- a/src/sunstone/public/app/tabs/vms-tab/buttons.js
+++ b/src/sunstone/public/app/tabs/vms-tab/buttons.js
@@ -200,25 +200,25 @@ define(function(require) {
     },
     "VM.lockA" : {
       type: "action",
-      text: Locale.tr("Admin") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Admin actions")) + "</span>",
+      text: Locale.tr("Admin"),
       layout: "lock_buttons",
       data: 3
     },
     "VM.lockM" : {
       type: "action",
-      text: Locale.tr("Manage") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Manage actions")) + "</span>",
+      text: Locale.tr("Manage"),
       layout: "lock_buttons",
       data: 2
     },
     "VM.lockU" : {
       type: "action",
-      text: Locale.tr("Use") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Use actions")) + "</span>",
+      text: Locale.tr("Use"),
       layout: "lock_buttons",
       data: 1
     },
     "VM.unlock" : {
       type: "action",
-      text: Locale.tr("Unlock") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Unlock all actions")) + "</span>",
+      text: Locale.tr("Unlock"),
       layout: "lock_buttons"
     }
   }
diff --git a/src/sunstone/public/app/tabs/vms-tab/hooks/header.js b/src/sunstone/public/app/tabs/vms-tab/hooks/header.js
index e2a201fb6e..ecf19ee1db 100644
--- a/src/sunstone/public/app/tabs/vms-tab/hooks/header.js
+++ b/src/sunstone/public/app/tabs/vms-tab/hooks/header.js
@@ -49,10 +49,9 @@ define(function(require) {
     $('.resource-info-header-small', '#' + TAB_ID).text(state);
 
     if (element.LOCK){
-      $('.resource-lock-header-small', '#' + TAB_ID).html("<i class='header-title fa fa-lock'> "+Locale.tr(Humanize.lock_to_str(element.LOCK.LOCKED))+"</i>");
-      $('.resource-lock-header-small', '#' + TAB_ID).show();
+      $('.resource-lock-header-small', '#' + contextTabId).html("<span data-tooltip aria-haspopup='true' class='has-tip' data-disable-hover='false' tabindex='1' title="+Locale.tr(Humanize.lock_to_str(element.LOCK.LOCKED))+"><i class='fa fa-lock fa-2x'/></span>");
     } else {
-      $('.resource-lock-header-small', '#' + TAB_ID).hide();
+      $('.resource-lock-header-small', '#' + contextTabId).html("<i style='color: #cacedd;' class='fa fa-unlock-alt fa-2x'/>");
     }
   }
 
diff --git a/src/sunstone/public/app/tabs/vnets-tab/buttons.js b/src/sunstone/public/app/tabs/vnets-tab/buttons.js
index db19b24136..a7dcdfc027 100644
--- a/src/sunstone/public/app/tabs/vnets-tab/buttons.js
+++ b/src/sunstone/public/app/tabs/vnets-tab/buttons.js
@@ -77,25 +77,25 @@ define(function(require) {
     },
     "Network.lockA" : {
       type: "action",
-      text: Locale.tr("Admin") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Admin actions")) + "</span>",
+      text: Locale.tr("Admin"),
       layout: "lock_buttons",
       data: 3
     },
     "Network.lockM" : {
       type: "action",
-      text: Locale.tr("Manage") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Manage actions")) + "</span>",
+      text: Locale.tr("Manage"),
       layout: "lock_buttons",
       data: 2
     },
     "Network.lockU" : {
       type: "action",
-      text: Locale.tr("Use") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Use actions")) + "</span>",
+      text: Locale.tr("Use"),
       layout: "lock_buttons",
       data: 1
     },
     "Network.unlock" : {
       type: "action",
-      text: Locale.tr("Unlock") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Unlock all actions")) + "</span>",
+      text: Locale.tr("Unlock"),
       layout: "lock_buttons"
     }
   };
diff --git a/src/sunstone/public/app/tabs/vrouters-tab/buttons.js b/src/sunstone/public/app/tabs/vrouters-tab/buttons.js
index a73ed8ec77..ca2b3099b4 100644
--- a/src/sunstone/public/app/tabs/vrouters-tab/buttons.js
+++ b/src/sunstone/public/app/tabs/vrouters-tab/buttons.js
@@ -57,25 +57,25 @@ define(function(require) {
     },
     "VirtualRouter.lockA" : {
       type: "action",
-      text: Locale.tr("Admin") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Admin actions")) + "</span>",
+      text: Locale.tr("Admin"),
       layout: "lock_buttons",
       data: 3
     },
     "VirtualRouter.lockM" : {
       type: "action",
-      text: Locale.tr("Manage") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Manage actions")) + "</span>",
+      text: Locale.tr("Manage"),
       layout: "lock_buttons",
       data: 2
     },
     "VirtualRouter.lockU" : {
       type: "action",
-      text: Locale.tr("Use") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Lock Use actions")) + "</span>",
+      text: Locale.tr("Use"),
       layout: "lock_buttons",
       data: 1
     },
     "VirtualRouter.unlock" : {
       type: "action",
-      text: Locale.tr("Unlock") + "<span class='right'>&nbsp;" + Tips.html(Locale.tr("Unlock all actions")) + "</span>",
+      text: Locale.tr("Unlock"),
       layout: "lock_buttons"
     }
   };

From 3cd612540feb6fc48d209ec160722ff54ee955b1 Mon Sep 17 00:00:00 2001
From: "Ruben S. Montero" <rsmontero@opennebula.org>
Date: Thu, 25 Jan 2018 12:04:35 +0100
Subject: [PATCH 6/6] B #1412: Fix missing condition when image was locked

---
 include/ImageManager.h           | 12 ++++----
 include/ImagePool.h              |  5 ++--
 src/image/ImageManagerActions.cc | 47 ++++++++++++++++++--------------
 src/image/ImagePool.cc           |  8 +++---
 src/vm/VirtualMachineDisk.cc     |  4 +--
 5 files changed, 42 insertions(+), 34 deletions(-)

diff --git a/include/ImageManager.h b/include/ImageManager.h
index 6548eb28a1..b205c3d59d 100644
--- a/include/ImageManager.h
+++ b/include/ImageManager.h
@@ -94,20 +94,20 @@ public:
      *  Try to acquire an image from the repository for a VM.
      *    @param image_id id of image
      *    @param error string describing the error
-     *    @param attach indicates that are trying to make an attachment of the image
+     *    @param attach true if attaching the image to a VM
      *    @return pointer to the image or 0 if could not be acquired
      */
-    Image * acquire_image(int vm_id, int image_id, string& error, bool attach);
+    Image * acquire_image(int vm_id, int image_id, bool attach, string& error);
 
     /**
      *  Try to acquire an image from the repository for a VM.
      *    @param name of the image
      *    @param id of owner
      *    @param error string describing the error
-     *    @param attach indicates that are trying to make an attachment of the image
+     *    @param attach true if attaching the image to a VM
      *    @return pointer to the image or 0 if could not be acquired
      */
-    Image * acquire_image(int vm_id, const string& name, int uid, string& error, bool attach);
+    Image * acquire_image(int vm_id, const string& name, int uid, bool attach, string& error);
 
     /**
      *  Releases an image and triggers any needed operations in the repo
@@ -360,10 +360,10 @@ private:
     /**
      *  Acquires an image updating its state.
      *    @param image pointer to image, it should be locked
-     *    @param attach indicates that are trying to make an attachment of the image
+     *    @param attach true if attaching the image to a VM
      *    @return 0 on success
      */
-    int acquire_image(int vm_id, Image *img, string& error, bool attach);
+    int acquire_image(int vm_id, Image *img, bool attach, string& error);
 
     /**
      *  Moves a file to an image in the repository
diff --git a/include/ImagePool.h b/include/ImagePool.h
index d38faa8e3a..96c453282d 100644
--- a/include/ImagePool.h
+++ b/include/ImagePool.h
@@ -154,6 +154,7 @@ public:
      *    @param uid of VM owner (to look for the image id within its images)
      *    @param image_id on success returns the acquired image id
      *    @param snaps list of snapshots associated to this image
+     *    @param attach true if attaching the image to a VM
      *    @param error_str string describing the error
      *
      *    @return 0 on success, -1 otherwise
@@ -166,8 +167,8 @@ public:
                      int                uid,
                      int&               image_id,
                      Snapshots **       snaps,
-                     string&            error_str,
-                     bool               attach);
+                     bool               attach,
+                     string&            error_str);
     /**
      *  Generates a DISK attribute for VM templates using the Image metadata
      *
diff --git a/src/image/ImageManagerActions.cc b/src/image/ImageManagerActions.cc
index d4703507d7..9af29d6f14 100644
--- a/src/image/ImageManagerActions.cc
+++ b/src/image/ImageManagerActions.cc
@@ -25,7 +25,8 @@
 /* -------------------------------------------------------------------------- */
 /* -------------------------------------------------------------------------- */
 
-Image * ImageManager::acquire_image(int vm_id, int image_id, string& error, bool attach)
+Image * ImageManager::acquire_image(int vm_id, int image_id, bool attach,
+        string& error)
 {
     Image * img;
     int     rc;
@@ -41,7 +42,7 @@ Image * ImageManager::acquire_image(int vm_id, int image_id, string& error, bool
         return 0;
     }
 
-    rc = acquire_image(vm_id, img, error, attach);
+    rc = acquire_image(vm_id, img, attach, error);
 
     if ( rc != 0 )
     {
@@ -54,7 +55,8 @@ Image * ImageManager::acquire_image(int vm_id, int image_id, string& error, bool
 
 /* -------------------------------------------------------------------------- */
 
-Image * ImageManager::acquire_image(int vm_id, const string& name, int uid, string& error, bool attach)
+Image * ImageManager::acquire_image(int vm_id, const string& name, int uid,
+        bool attach, string& error)
 {
     Image * img;
     int     rc;
@@ -71,7 +73,7 @@ Image * ImageManager::acquire_image(int vm_id, const string& name, int uid, stri
         return 0;
     }
 
-    rc = acquire_image(vm_id, img, error, attach);
+    rc = acquire_image(vm_id, img, attach, error);
 
     if ( rc != 0 )
     {
@@ -84,7 +86,7 @@ Image * ImageManager::acquire_image(int vm_id, const string& name, int uid, stri
 
 /* -------------------------------------------------------------------------- */
 
-int ImageManager::acquire_image(int vm_id, Image *img, string& error, bool attach)
+int ImageManager::acquire_image(int vm_id, Image *img, bool attach, string& error)
 {
     int rc = 0;
 
@@ -129,24 +131,26 @@ int ImageManager::acquire_image(int vm_id, Image *img, string& error, bool attac
             if (attach)
             {
                 oss << "Cannot acquire image " << img->get_oid()
-                << ", it is locked";
+                    << ", it is locked";
 
                 error = oss.str();
                 rc    = -1;
             }
-
-            img->inc_running(vm_id);
-
-            if ( img->is_persistent() )
-            {
-                img->set_state(Image::LOCKED_USED_PERS);
-            }
             else
             {
-                img->set_state(Image::LOCKED_USED);
-            }
+                img->inc_running(vm_id);
 
-            ipool->update(img);
+                if ( img->is_persistent() )
+                {
+                    img->set_state(Image::LOCKED_USED_PERS);
+                }
+                else
+                {
+                    img->set_state(Image::LOCKED_USED);
+                }
+
+                ipool->update(img);
+            }
         break;
 
         case Image::USED_PERS:
@@ -162,18 +166,21 @@ int ImageManager::acquire_image(int vm_id, Image *img, string& error, bool attac
             img->inc_running(vm_id);
             ipool->update(img);
         break;
+
         case Image::LOCKED_USED:
             if (attach)
             {
                 oss << "Cannot acquire image " << img->get_oid()
-                << ", it is locked";
+                    << ", it is locked";
 
                 error = oss.str();
                 rc    = -1;
             }
-
-            img->inc_running(vm_id);
-            ipool->update(img);
+            else
+            {
+                img->inc_running(vm_id);
+                ipool->update(img);
+            }
         break;
 
         case Image::INIT:
diff --git a/src/image/ImagePool.cc b/src/image/ImagePool.cc
index 85f5145e94..b15520e5b3 100644
--- a/src/image/ImagePool.cc
+++ b/src/image/ImagePool.cc
@@ -297,8 +297,8 @@ int ImagePool::acquire_disk(int               vm_id,
                             int               uid,
                             int&              image_id,
                             Snapshots **      snap,
-                            string&           error_str,
-                            bool              attach)
+                            bool              attach,
+                            string&           error_str)
 {
     string  source;
     Image * img = 0;
@@ -315,7 +315,7 @@ int ImagePool::acquire_disk(int               vm_id,
 
     if ( disk->vector_value("IMAGE_ID", iid) == 0 )
     {
-        img = imagem->acquire_image(vm_id, iid, error_str, attach);
+        img = imagem->acquire_image(vm_id, iid, attach, error_str);
 
         if ( img == 0 )
         {
@@ -337,7 +337,7 @@ int ImagePool::acquire_disk(int               vm_id,
             return -1;
         }
 
-        img = imagem->acquire_image(vm_id, source, uiid, error_str, attach);
+        img = imagem->acquire_image(vm_id, source, uiid, attach, error_str);
 
         if ( img == 0 )
         {
diff --git a/src/vm/VirtualMachineDisk.cc b/src/vm/VirtualMachineDisk.cc
index 53951c6afb..ecfacee071 100644
--- a/src/vm/VirtualMachineDisk.cc
+++ b/src/vm/VirtualMachineDisk.cc
@@ -751,7 +751,7 @@ int VirtualMachineDisks::get_images(int vm_id, int uid, const std::string& tsys,
         }
 
         if ( ipool->acquire_disk(vm_id, disk, disk_id, image_type, dev_prefix,
-                uid, image_id, &snapshots, error_str, false) != 0 )
+                uid, image_id, &snapshots, false, error_str) != 0 )
         {
             oss << "DISK " << disk_id << ": " << error_str;
             error_str = oss.str();
@@ -1076,7 +1076,7 @@ VirtualMachineDisk * VirtualMachineDisks::set_up_attach(int vmid, int uid,
     VirtualMachineDisk * disk = new VirtualMachineDisk(vdisk, max_disk_id + 1);
 
     int rc = ipool->acquire_disk(vmid, disk, max_disk_id + 1, img_type,
-                         dev_prefix, uid, image_id, &snap, error, true);
+                         dev_prefix, uid, image_id, &snap, true, error);
     if ( rc != 0 )
     {
         return 0;