Module: OpenNebula::LockableExt

Defined in:
lib/opennebula/lockable_ext.rb

Overview

Module to decorate Lockable classes with the following methods:

- Lock
- Unlock
- Synchronize

rubocop:disable Style/ClassAndModuleChildren

Constant Summary collapse

LOCK_TIMEOUT =

Expire timeout for locking operation

120

Class Method Summary collapse

Class Method Details

.extend_object(obj) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# 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) ⇒ Boolean

Check if object is lockable or not

Parameters:

  • obj (Object or Class)

    Object to check class

Returns:

  • (Boolean)

Raises:

  • (StandardError)


125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/opennebula/lockable_ext.rb', line 125

def self.lockable?(obj)
    # Lockable classes
    lockable = [
        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) ⇒ Object



41
42
43
44
45
46
# 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