Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

initial lock functionality commit

  • Loading branch information...
commit 8aea573bd2e44e152fb4ef1627640bab1818dede 1 parent 675ca7c
Trey Morris authored December 28, 2010
73  nova/api/openstack/__init__.py
@@ -22,6 +22,7 @@
22 22
 
23 23
 import json
24 24
 import time
  25
+import functools
25 26
 
26 27
 import logging
27 28
 import routes
@@ -113,3 +114,75 @@ def __init__(self):
113 114
                         controller=sharedipgroups.Controller())
114 115
 
115 116
         super(APIRouter, self).__init__(mapper)
  117
+
  118
+
  119
+#class CheckLock(object):
  120
+#    """
  121
+#    decorator used for preventing action against locked instances
  122
+#    unless, of course, you happen to be admin
  123
+#
  124
+#    """
  125
+#    def __init__(self, function):
  126
+#        self.function = function
  127
+#
  128
+#    def __getattribute__(self, attr):
  129
+#        if attr == "function":
  130
+#            return super(CheckLock, self).__getattribute__(attr)
  131
+#        return self.function.__getattribute__(attr)
  132
+#
  133
+#    def __call__(self, *args, **kwargs):
  134
+#        logging.info(_("Calling %s. Checking locks and privileges"),
  135
+#                                             self.function.__name__)
  136
+#
  137
+#        # get req
  138
+#        if 'req' is in kwargs:
  139
+#            req = kwargs['req']
  140
+#        else:
  141
+#            req = args[1]
  142
+#
  143
+#        # check table for lock
  144
+#        locked = True
  145
+#        if(locked):
  146
+#            # check context for admin
  147
+#            if(req.environ['nova.context'].is_admin):
  148
+#                self.function(*args, **kwargs)
  149
+#            else:
  150
+#                pass
  151
+#                # return 404
  152
+#
  153
+#    def __get__(self, obj, objtype):
  154
+#        f = functools.partial(self.__call__, obj)
  155
+#        f.__doc__ = self.function.__doc__
  156
+#        return f
  157
+
  158
+
  159
+
  160
+
  161
+#def checks_lock(function):
  162
+#    """
  163
+#    decorator used for preventing action against locked instances
  164
+#    unless, of course, you happen to be admin
  165
+#
  166
+#    """
  167
+#
  168
+#    @functools.wraps(function)
  169
+#    def decorated_function(*args, **kwargs):
  170
+#
  171
+#        # check table for lock
  172
+#        locked = True
  173
+#        if(locked):
  174
+#            try:
  175
+#                # get context from req and check for admin
  176
+#                if 'req' is in kwargs:
  177
+#                    req = kwargs['req']
  178
+#                else:
  179
+#                    req = args[1]
  180
+#                if(req.environ['nova.context'].is_admin):
  181
+#                    function(*args, **kwargs)
  182
+#                else:
  183
+#                    pass
  184
+#                    # return 404
  185
+#            except:
  186
+#                logging.error(_("CheckLock: error getting context"))
  187
+#
  188
+#    return decorated_function
86  nova/api/openstack/servers.py
@@ -35,6 +35,40 @@
35 35
 LOG.setLevel(logging.DEBUG)
36 36
 
37 37
 
  38
+def checks_lock(function):
  39
+    """
  40
+    decorator used for preventing action against locked instances
  41
+    unless, of course, you happen to be admin
  42
+
  43
+    """
  44
+
  45
+    @functools.wraps(function)
  46
+    def decorated_function(*args, **kwargs):
  47
+
  48
+        # grab args to function
  49
+        try:
  50
+            if 'req' is in kwargs:
  51
+                req = kwargs['req']
  52
+            else:
  53
+                req = args[1]
  54
+            if 'id' is in kwargs:
  55
+                _id = kwargs['id']
  56
+            else:
  57
+                req = args[2]
  58
+            context = req.environ['nova.context']
  59
+        except:
  60
+            logging.error(_("CheckLock: argument error"))
  61
+
  62
+        # if locked and admin call function, otherwise 404
  63
+        if(compute_api.ComputeAPI().get_lock(context, _id)):
  64
+            if(req.environ['nova.context'].is_admin):
  65
+                function(*args, **kwargs)
  66
+        # return 404
  67
+        return faults.Fault(exc.HTTPUnprocessableEntity())
  68
+
  69
+    return decorated_function
  70
+
  71
+
38 72
 def _entity_list(entities):
39 73
     """ Coerces a list of servers into proper dictionary format """
40 74
     return dict(servers=entities)
@@ -104,6 +138,7 @@ def _items(self, req, entity_maker):
104 138
         res = [entity_maker(inst)['server'] for inst in limited_list]
105 139
         return _entity_list(res)
106 140
 
  141
+    @checks_lock
107 142
     def show(self, req, id):
108 143
         """ Returns server details by server id """
109 144
         try:
@@ -113,6 +148,7 @@ def show(self, req, id):
113 148
         except exception.NotFound:
114 149
             return faults.Fault(exc.HTTPNotFound())
115 150
 
  151
+    @checks_lock
116 152
     def delete(self, req, id):
117 153
         """ Destroys a server """
118 154
         try:
@@ -140,6 +176,7 @@ def create(self, req):
140 176
             key_data=key_pair['public_key'])
141 177
         return _entity_inst(instances[0])
142 178
 
  179
+    @checks_lock
143 180
     def update(self, req, id):
144 181
         """ Updates the server name or password """
145 182
         inst_dict = self._deserialize(req.body, req)
@@ -160,6 +197,7 @@ def update(self, req, id):
160 197
             return faults.Fault(exc.HTTPNotFound())
161 198
         return exc.HTTPNoContent()
162 199
 
  200
+    @checks_lock
163 201
     def action(self, req, id):
164 202
         """ Multi-purpose method used to reboot, rebuild, and
165 203
         resize a server """
@@ -176,6 +214,51 @@ def action(self, req, id):
176 214
             return faults.Fault(exc.HTTPUnprocessableEntity())
177 215
         return exc.HTTPAccepted()
178 216
 
  217
+    def lock(self, req, id):
  218
+        """
  219
+        lock the instance with id
  220
+        admin only operation
  221
+
  222
+        """
  223
+        context = req.environ['nova.context']
  224
+        try:
  225
+            self.compute_api.lock(context, id)
  226
+        except:
  227
+            readable = traceback.format_exc()
  228
+            logging.error(_("Compute.api::lock %s"), readable)
  229
+            return faults.Fault(exc.HTTPUnprocessableEntity())
  230
+        return exc.HTTPAccepted()
  231
+
  232
+    def unlock(self, req, id):
  233
+        """
  234
+        unlock the instance with id
  235
+        admin only operation
  236
+
  237
+        """
  238
+        context = req.environ['nova.context']
  239
+        try:
  240
+            self.compute_api.unlock(context, id)
  241
+        except:
  242
+            readable = traceback.format_exc()
  243
+            logging.error(_("Compute.api::unlock %s"), readable)
  244
+            return faults.Fault(exc.HTTPUnprocessableEntity())
  245
+        return exc.HTTPAccepted()
  246
+
  247
+    def get_lock(self, req, id):
  248
+        """
  249
+        return the boolean state of (instance with id)'s lock
  250
+
  251
+        """
  252
+        context = req.environ['nova.context']
  253
+        try:
  254
+            self.compute_api.get_lock(context, id)
  255
+        except:
  256
+            readable = traceback.format_exc()
  257
+            logging.error(_("Compute.api::get_lock %s"), readable)
  258
+            return faults.Fault(exc.HTTPUnprocessableEntity())
  259
+        return exc.HTTPAccepted()
  260
+
  261
+    @checks_lock
179 262
     def pause(self, req, id):
180 263
         """ Permit Admins to Pause the server. """
181 264
         ctxt = req.environ['nova.context']
@@ -187,6 +270,7 @@ def pause(self, req, id):
187 270
             return faults.Fault(exc.HTTPUnprocessableEntity())
188 271
         return exc.HTTPAccepted()
189 272
 
  273
+    @checks_lock
190 274
     def unpause(self, req, id):
191 275
         """ Permit Admins to Unpause the server. """
192 276
         ctxt = req.environ['nova.context']
@@ -198,6 +282,7 @@ def unpause(self, req, id):
198 282
             return faults.Fault(exc.HTTPUnprocessableEntity())
199 283
         return exc.HTTPAccepted()
200 284
 
  285
+    @checks_lock
201 286
     def suspend(self, req, id):
202 287
         """permit admins to suspend the server"""
203 288
         context = req.environ['nova.context']
@@ -209,6 +294,7 @@ def suspend(self, req, id):
209 294
             return faults.Fault(exc.HTTPUnprocessableEntity())
210 295
         return exc.HTTPAccepted()
211 296
 
  297
+    @checks_lock
212 298
     def resume(self, req, id):
213 299
         """permit admins to resume the server from suspend"""
214 300
         context = req.environ['nova.context']
35  nova/compute/api.py
@@ -141,7 +141,8 @@ def create_instances(self, context, instance_type, image_id, min_count=1,
141 141
             'display_description': description,
142 142
             'user_data': user_data or '',
143 143
             'key_name': key_name,
144  
-            'key_data': key_data}
  144
+            'key_data': key_data,
  145
+            'locked': False}
145 146
 
146 147
         elevated = context.elevated()
147 148
         instances = []
@@ -319,3 +320,35 @@ def unrescue(self, context, instance_id):
319 320
                  self.db.queue_get_for(context, FLAGS.compute_topic, host),
320 321
                  {"method": "unrescue_instance",
321 322
                   "args": {"instance_id": instance['id']}})
  323
+
  324
+    def lock(self, context, instance_id):
  325
+        """
  326
+        lock the instance with instance_id
  327
+
  328
+        """
  329
+        instance = self.get_instance(context, instance_id)
  330
+        host = instance['host']
  331
+        rpc.cast(context,
  332
+                 self.db.queue_get_for(context, FLAGS.compute_topic, host),
  333
+                 {"method": "lock_instance",
  334
+                  "args": {"instance_id": instance['id']}})
  335
+
  336
+    def unlock(self, context, instance_id):
  337
+        """
  338
+        unlock the instance with instance_id
  339
+
  340
+        """
  341
+        instance = self.get_instance(context, instance_id)
  342
+        host = instance['host']
  343
+        rpc.cast(context,
  344
+                 self.db.queue_get_for(context, FLAGS.compute_topic, host),
  345
+                 {"method": "unlock_instance",
  346
+                  "args": {"instance_id": instance['id']}})
  347
+
  348
+    def get_lock(self, context, instance_id):
  349
+        """
  350
+        return the boolean state of (instance with instance_id)'s lock
  351
+
  352
+        """
  353
+        instance = self.get_instance(context, instance_id)
  354
+        return instance['locked']
24  nova/compute/manager.py
@@ -330,6 +330,30 @@ def resume_instance(self, context, instance_id):
330 330
                                                        result))
331 331
 
332 332
     @exception.wrap_exception
  333
+    def lock_instance(self, context, instance_id):
  334
+        """
  335
+        lock the instance with instance_id
  336
+
  337
+        """
  338
+        context = context.elevated()
  339
+        instance_ref = self.db.instance_get(context, instance_id)
  340
+
  341
+        logging.debug(_('instance %s: locking'), instance_ref['internal_id'])
  342
+        self.db.instance_set_lock(context, instance_id, True)
  343
+
  344
+    @exception.wrap_exception
  345
+    def unlock_instance(self, context, instance_id):
  346
+        """
  347
+        unlock the instance with instance_id
  348
+
  349
+        """
  350
+        context = context.elevated()
  351
+        instance_ref = self.db.instance_get(context, instance_id)
  352
+
  353
+        logging.debug(_('instance %s: unlocking'), instance_ref['internal_id'])
  354
+        self.db.instance_set_lock(context, instance_id, False)
  355
+
  356
+    @exception.wrap_exception
333 357
     def get_console_output(self, context, instance_id):
334 358
         """Send the console output for an instance."""
335 359
         context = context.elevated()
22  nova/db/sqlalchemy/api.py
@@ -856,6 +856,28 @@ def instance_action_create(context, values):
856 856
     return action_ref
857 857
 
858 858
 
  859
+@require_admin_context
  860
+def instance_set_lock(context, instance_id, lock):
  861
+    """
  862
+    twiddle the locked bit in the db
  863
+    lock is a boolean
  864
+
  865
+    """
  866
+    db.instance_update(context,
  867
+                       instance_id,
  868
+                       {'locked': lock})
  869
+
  870
+
  871
+#@require_admin_context
  872
+#def instance_is_locked(context, instance_id):
  873
+#    """
  874
+#    return the boolean state of (instance with instance_id)'s lock
  875
+#
  876
+#    """
  877
+#    instance_ref = instance_get(context, instance_id)
  878
+#    return instance_ref['locked']
  879
+
  880
+
859 881
 ###################
860 882
 
861 883
 
2  nova/db/sqlalchemy/models.py
@@ -224,6 +224,8 @@ def name(self):
224 224
     display_name = Column(String(255))
225 225
     display_description = Column(String(255))
226 226
 
  227
+    locked = Column(Boolean)
  228
+
227 229
     # TODO(vish): see Ewan's email about state improvements, probably
228 230
     #             should be in a driver base class or some such
229 231
     # vmstate_state = running, halted, suspended, paused

0 notes on commit 8aea573

Please sign in to comment.
Something went wrong with that request. Please try again.