module OpenNebula::LockableExt

Module to decorate Lockable classes with the following methods:

- Lock
- Unlock
- Synchronize

rubocop:disable Style/ClassAndModuleChildren

Constants

LOCK_TIMEOUT

Expire timeout for locking operation

Public Class Methods

extend_object(obj) click to toggle source
Calls superclass method
# File lib/opennebula/lockable_ext.rb, line 48
def self.extend_object(obj)
    lockable?(obj)

    class << obj

        # Locks the object
        #
        # @param level [Integer] Lock level
        # @param test  [Boolean] Check if the object is already locked
        #
        # use    -> level = 1
        # manage -> level = 2
        # admin  -> level = 3
        # all    -> level = 4
        #
        # @return [Integer, OpenNebula::Error]
        #   - Object ID if the lock was granted
        #   - Error otherwise
        def lock(level, test = false)
            return Error.new('ID not defined') unless @pe_id

            @client.call(@lock_method, @pe_id, level, test)
        end

        # Unlocks this object
        #
        # @return [nil, OpenNebula::Error]
        #   - nil in case of success
        #   - Error otherwise
        def unlock
            @client.call(@unlock_method, @pe_id)
        end

        # Executes an operation with lock granted
        #
        # @param level [Integer] Lock level
        #
        # @return [Operation rc, OpenNebula::Error]
        #   - Operation return code
        #   - Error otherwise
        def synchronize(level)
            rc = lock(level, true)

            if OpenNebula.is_error?(rc)
                # If test check, core returns timestamp when it was locked
                lock_time = Time.at(Integer(rc.message.split(' ')[1]))
                c_time    = Time.now

                # If the timeout has not yet expired, return error
                if (c_time - lock_time) < LOCK_TIMEOUT
                    return Error.new('Object is locked')
                end

                rc = lock(level)

                return rc if OpenNebula.is_error?(rc)
            end

            ret = yield if block_given?

            unless OpenNebula.is_error?(info)
                rc = unlock

                return rc if OpenNebula.is_error?(rc)
            end

            ret
        end

    end

    super
end
lockable?(obj) click to toggle source

Check if object is lockable or not

@param obj [Object or Class] Object to check class

# File lib/opennebula/lockable_ext.rb, line 125
def self.lockable?(obj)
    # Lockable classes
    lockable = [
        OpenNebula::BackupJob,
        OpenNebula::Document,
        OpenNebula::Hook,
        OpenNebula::Image,
        OpenNebula::MarketPlaceApp,
        OpenNebula::Template,
        OpenNebula::VirtualMachine,
        OpenNebula::VirtualNetwork,
        OpenNebula::VirtualRouter,
        OpenNebula::VMGroup,
        OpenNebula::VNTemplate
    ]

    # Get obj class to find parents in lockable class
    # rubocop:disable Style/TernaryParentheses
    (obj.is_a? Class) ? o_class = obj : o_class = obj.class
    # rubocop:enable Style/TernaryParentheses

    found   = false
    i_class = o_class

    while i_class
        if lockable.include?(i_class)
            found = true
            break
        end

        i_class = i_class.superclass
    end

    return if found

    raise StandardError, "Cannot extend #{o_class} with LockableExt"
end
make_lockable(obj, methods) click to toggle source
# File lib/opennebula/lockable_ext.rb, line 41
def self.make_lockable(obj, methods)
    obj.instance_variable_set(:@lock_method, methods[:lock])
    obj.instance_variable_set(:@unlock_method, methods[:unlock])

    obj.extend(OpenNebula::LockableExt)
end