3535LOG .setLevel (logging .DEBUG )
3636
3737
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+
3872def _entity_list (entities ):
3973 """ Coerces a list of servers into proper dictionary format """
4074 return dict (servers = entities )
@@ -104,6 +138,7 @@ def _items(self, req, entity_maker):
104138 res = [entity_maker (inst )['server' ] for inst in limited_list ]
105139 return _entity_list (res )
106140
141+ @checks_lock
107142 def show (self , req , id ):
108143 """ Returns server details by server id """
109144 try :
@@ -113,6 +148,7 @@ def show(self, req, id):
113148 except exception .NotFound :
114149 return faults .Fault (exc .HTTPNotFound ())
115150
151+ @checks_lock
116152 def delete (self , req , id ):
117153 """ Destroys a server """
118154 try :
@@ -140,6 +176,7 @@ def create(self, req):
140176 key_data = key_pair ['public_key' ])
141177 return _entity_inst (instances [0 ])
142178
179+ @checks_lock
143180 def update (self , req , id ):
144181 """ Updates the server name or password """
145182 inst_dict = self ._deserialize (req .body , req )
@@ -160,6 +197,7 @@ def update(self, req, id):
160197 return faults .Fault (exc .HTTPNotFound ())
161198 return exc .HTTPNoContent ()
162199
200+ @checks_lock
163201 def action (self , req , id ):
164202 """ Multi-purpose method used to reboot, rebuild, and
165203 resize a server """
@@ -176,6 +214,51 @@ def action(self, req, id):
176214 return faults .Fault (exc .HTTPUnprocessableEntity ())
177215 return exc .HTTPAccepted ()
178216
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
179262 def pause (self , req , id ):
180263 """ Permit Admins to Pause the server. """
181264 ctxt = req .environ ['nova.context' ]
@@ -187,6 +270,7 @@ def pause(self, req, id):
187270 return faults .Fault (exc .HTTPUnprocessableEntity ())
188271 return exc .HTTPAccepted ()
189272
273+ @checks_lock
190274 def unpause (self , req , id ):
191275 """ Permit Admins to Unpause the server. """
192276 ctxt = req .environ ['nova.context' ]
@@ -198,6 +282,7 @@ def unpause(self, req, id):
198282 return faults .Fault (exc .HTTPUnprocessableEntity ())
199283 return exc .HTTPAccepted ()
200284
285+ @checks_lock
201286 def suspend (self , req , id ):
202287 """permit admins to suspend the server"""
203288 context = req .environ ['nova.context' ]
@@ -209,6 +294,7 @@ def suspend(self, req, id):
209294 return faults .Fault (exc .HTTPUnprocessableEntity ())
210295 return exc .HTTPAccepted ()
211296
297+ @checks_lock
212298 def resume (self , req , id ):
213299 """permit admins to resume the server from suspend"""
214300 context = req .environ ['nova.context' ]
0 commit comments