1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 """
17 Abstract classes for resource management
18 """
19
20 import copy
21 import inspect
22 import time
23
24 from . import constant
25 from . import exception
26 from . import mapper
27 from . import utils
28
29
30 WRAPPER_METHODS = []
31 BAD_ATTRS = ['self']
32
33
35 """Base class for resources."""
36
37 _id = None
38 _attrs = []
39 _loaded = True
40 _sub_manager_list = {}
41 _state_attr = 'status'
42 _stable_state = []
43
44 - def __init__(self, manager, *args, **kwargs):
83
85 if not isinstance(other, Resource):
86 return False
87 return self._id == other._id
88
90 if not isinstance(other, Resource):
91 return True
92 return self._id != other._id
93
95 if 'name' in self._attrs and self._id_attr != 'name' and self._loaded:
96 return '<%s.%s (%s="%s", name="%s")>' % (
97 self.__module__, self.__class__.__name__, self._id_attr,
98 self._id, self.name)
99 empty = ''
100 if not self._loaded:
101 empty = ' empty'
102 return '<%s.%s (%s="%s"%s)>' % (
103 self.__module__, self.__class__.__name__, self._id_attr,
104 self._id, empty)
105
107 if self._verbose:
108 attrs = self.get_attrs()
109 return '<%s.%s (%s)>' % (
110 self.__module__, self.__class__.__name__, attrs)
111 else:
112 return self.__repr__()
113
123
125 _kwargs = copy.copy(kwargs)
126 for attr in self._attrs:
127 if attr in _kwargs:
128 setattr(self, attr, _kwargs.pop(attr))
129 if not self._has_extra_attr:
130 return
131 for key, value in _kwargs.items():
132 if not key.startswith('_') and key not in BAD_ATTRS:
133 setattr(self, key, value)
134
136 """
137 Clear attributes
138
139 @rtype: None
140 """
141 ret = {}
142 if not self._loaded:
143 return
144 for key in dir(self):
145 if key.startswith('_'):
146 continue
147 value = getattr(self, key)
148 if inspect.ismethod(value) or inspect.isfunction(value):
149 continue
150 delattr(self, key)
151
153 """
154 Query ID of a resource
155
156 @return: ID
157 @rtype: str
158 """
159 return self._id
160
162 """
163 Aquire attributes as a dictionary
164
165 @return: attributes
166 @rtype: dict
167 """
168 ret = {}
169 if not self._loaded:
170 self.reload()
171 self._loaded = True
172 for key in dir(self):
173 if key.startswith('_'):
174 continue
175 value = getattr(self, key)
176 if inspect.ismethod(value) or inspect.isfunction(value):
177 continue
178 ret[key] = value
179 return ret
180
182 """
183 (Re)load attributes of a resource
184
185 @return: Whether attributes are updated
186 @rtype: bool
187 """
188 x = self._manager.get(getattr(self, self._id_attr))
189 if x:
190 self._clear_attrs()
191 self._set_attrs(x.__dict__)
192 self._loaded = True
193 return True
194 return False
195
208
216
218 """
219 Wait for task finished
220
221 @keyword count: Maximum polling time
222 @type count: int
223 @keyword interval: Polling interval in seconds
224 @type interval: int
225 @rtype: None
226 """
227 for i in range(count):
228 time.sleep(interval)
229 try:
230 self.reload()
231 except exception.NotFound:
232 return
233 if getattr(self, self._state_attr, None) in self._stable_state:
234 return
235
236
238 """Base class for resource managers."""
239
240 resource_class = None
241 service_type = ''
242 _attr_mapping = []
243 _has_detail = True
244 _has_extra_attr = False
245 _hidden_methods = None
246 _json_resource_key = ''
247 _json_resources_key = ''
248 _id_attr = 'id'
249 _update_method = 'put'
250 _url_resource_path = ''
251 _url_resource_list_path = ''
252
253 - def __init__(self, client, verbose=False, **kwargs):
254 """
255 Create a Manager object
256
257 kwargs: options
258
259 @param client: client object
260 @type client: yakumo.Client
261 @keyword verbose: Whether str(Resource) displays all attributes
262 @type verbose: bool
263 @return: Manager object
264 @rtype: yakumo.base.Manager
265 """
266 self._client = client
267 self._session = client._session
268 self._http = self._session.get_proxy(self.service_type)
269 self._to_json_mapping = {}
270 self._to_attr_mapping = {}
271 self._verbose = verbose
272 if not self._url_resource_list_path:
273 self._url_resource_list_path = self._url_resource_path
274 if self.resource_class is None:
275 return
276 mapper.make_mappings(self._attr_mapping,
277 self._to_json_mapping,
278 self._to_attr_mapping)
279 if self._hidden_methods is not None:
280 for method in self._hidden_methods:
281 setattr(self, method, self._no_such_api)
282
285
287 result = {}
288 for key, value in json_params.items():
289 _map = self._to_attr_mapping.get(key)
290 if _map is not None:
291 result[_map['attr']] = _map['mapper'].to_attr(self, value)
292 elif self._has_extra_attr and \
293 not key.startswith('_') and key not in BAD_ATTRS:
294 result[key] = value
295 return result
296
298 result = {}
299 for key, value in attrs.items():
300 if value is constant.UNDEF:
301 continue
302 _map = self._to_json_mapping.get(key)
303 if _map is not None:
304 result[_map['json_attr']] = \
305 _map['mapper'].to_json(self, value)
306 elif self._has_extra_attr \
307 and not key.startswith('_') and key not in BAD_ATTRS:
308 result[key] = value
309 return result
310
312 """
313 Create a resource object without attributes
314
315 @return: Resource object (empty)
316 @rtype: yakumo.base.Resource
317 """
318 if id is None:
319 return None
320 kwargs = {self._id_attr: id}
321 return self.resource_class(self, **kwargs)
322
337
356
379
380 - def find(self, **kwargs):
381 """
382 Query existing resource object matched the conditions
383
384 kwargs is key=value style query conditions.
385 Returns empty list if no matched resource.
386
387 @return: List of Resource object
388 @rtype: yakumo.base.Resource
389 """
390 return list(self._find_gen(**kwargs))
391
393 """
394 Aquire an existing resource object matched the conditions
395
396 kwargs is key=value style query conditions.
397 Returns None if no matched resource.
398
399 @return: Resource object
400 @rtype: yakumo.base.Resource
401 """
402 try:
403 return self._find_gen(**kwargs).next()
404 except StopIteration:
405 return None
406
408 """
409 Aquire an existing resource object
410
411 @return: List of Resource objects
412 @rtype: [yakumo.base.Resource]
413 """
414 return self.find()
415
416
418 """Base class for sub resource managers."""
419
420 - def __init__(self, parent_resource, *args, **kwargs):
429
430
432 """Base class for resource managers which don't use _json_resource_key."""
433
444
445
447 """Base class for resource managers which don't use _json_resource_key."""
448
449 _has_extra_attr = True
450
452 """
453 Create a new resource
454
455 kwargs: attributes of the resource
456
457 @return: Resource object (empty)
458 @rtype: yakumo.base.Resource
459 """
460 json_params = self._attr2json(kwargs)
461 ret = self._http.post(self._url_resource_path, data=json_params)
462 attrs = self._json2attr(ret)
463 return self.get_empty(attrs[self._id_attr])
464
466 """
467 Aquire an existing resource object
468
469 @param id: ID
470 @type id: str
471 @return: Resource object
472 @rtype: yakumo.base.Resource
473 """
474 try:
475 json_params = self._http.get(
476 utils.join_path(self._url_resource_path, id))
477 attrs = self._json2attr(json_params)
478 return self.resource_class(self, **attrs)
479 except exception.NotFound:
480 raise
481 except:
482 return None
483
484
486 """Base class for sub resource managers for GlanceV2Manager."""
487 pass
488