Package cm_api :: Package endpoints :: Module types
[hide private]
[frames] | no frames]

Source Code for Module cm_api.endpoints.types

   1  # Licensed to Cloudera, Inc. under one 
   2  # or more contributor license agreements.  See the NOTICE file 
   3  # distributed with this work for additional information 
   4  # regarding copyright ownership.  Cloudera, Inc. licenses this file 
   5  # to you under the Apache License, Version 2.0 (the 
   6  # "License"); you may not use this file except in compliance 
   7  # with the License.  You may obtain a copy of the License at 
   8  # 
   9  #     http://www.apache.org/licenses/LICENSE-2.0 
  10  # 
  11  # Unless required by applicable law or agreed to in writing, software 
  12  # distributed under the License is distributed on an "AS IS" BASIS, 
  13  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  14  # See the License for the specific language governing permissions and 
  15  # limitations under the License. 
  16   
  17  try: 
  18    import json 
  19  except ImportError: 
  20    import simplejson as json 
  21   
  22  import copy 
  23  import datetime 
  24  import time 
  25   
  26  __docformat__ = "epytext" 
27 28 -class Attr(object):
29 """ 30 Encapsulates information about an attribute in the JSON encoding of the 31 object. It identifies properties of the attribute such as whether it's 32 read-only, its type, etc. 33 """ 34 DATE_FMT = "%Y-%m-%dT%H:%M:%S.%fZ" 35
36 - def __init__(self, atype=None, rw=True, is_api_list=False):
37 self._atype = atype 38 self._is_api_list = is_api_list 39 self.rw = rw
40
41 - def to_json(self, value, preserve_ro):
42 """ 43 Returns the JSON encoding of the given attribute value. 44 45 If the value has a 'to_json_dict' object, that method is called. Otherwise, 46 the following values are returned for each input type: 47 - datetime.datetime: string with the API representation of a date. 48 - dictionary: if 'atype' is ApiConfig, a list of ApiConfig objects. 49 - python list: python list (or ApiList) with JSON encoding of items 50 - the raw value otherwise 51 """ 52 if hasattr(value, 'to_json_dict'): 53 return value.to_json_dict(preserve_ro) 54 elif isinstance(value, dict) and self._atype == ApiConfig: 55 return config_to_api_list(value) 56 elif isinstance(value, datetime.datetime): 57 return value.strftime(self.DATE_FMT) 58 elif isinstance(value, list) or isinstance(value, tuple): 59 if self._is_api_list: 60 return ApiList(value).to_json_dict() 61 else: 62 return [ self.to_json(x, preserve_ro) for x in value ] 63 else: 64 return value
65
66 - def from_json(self, resource_root, data):
67 """ 68 Parses the given JSON value into an appropriate python object. 69 70 This means: 71 - a datetime.datetime if 'atype' is datetime.datetime 72 - a converted config dictionary or config list if 'atype' is ApiConfig 73 - if the attr is an API list, an ApiList with instances of 'atype' 74 - an instance of 'atype' if it has a 'from_json_dict' method 75 - a python list with decoded versions of the member objects if the input 76 is a python list. 77 - the raw value otherwise 78 """ 79 if data is None: 80 return None 81 82 if self._atype == datetime.datetime: 83 return datetime.datetime.strptime(data, self.DATE_FMT) 84 elif self._atype == ApiConfig: 85 # ApiConfig is special. We want a python dictionary for summary views, 86 # but an ApiList for full views. Try to detect each case from the JSON 87 # data. 88 if not data['items']: 89 return { } 90 first = data['items'][0] 91 return json_to_config(data, len(first) == 2) 92 elif self._is_api_list: 93 return ApiList.from_json_dict(data, resource_root, self._atype) 94 elif isinstance(data, list): 95 return [ self.from_json(resource_root, x) for x in data ] 96 elif hasattr(self._atype, 'from_json_dict'): 97 return self._atype.from_json_dict(data, resource_root) 98 else: 99 return data
100
101 -class ROAttr(Attr):
102 """ 103 Subclass that just defines the attribute as read-only. 104 """
105 - def __init__(self, atype=None, is_api_list=False):
106 Attr.__init__(self, atype=atype, rw=False, is_api_list=is_api_list)
107
108 109 -def check_api_version(resource_root, min_version):
110 """ 111 Checks if the resource_root's API version it at least the given minimum 112 version. 113 """ 114 if resource_root.version < min_version: 115 raise Exception("API version %s is required but %s is in use." 116 % (min_version, resource_root.version))
117
118 119 -def call(method, path, ret_type, 120 ret_is_list=False, data=None, params=None, api_version=1):
121 """ 122 Generic function for calling a resource method and automatically dealing with 123 serialization of parameters and deserialization of return values. 124 125 @param method: method to call (must be bound to a resource; 126 e.g., "resource_root.get"). 127 @param path: the full path of the API method to call. 128 @param ret_type: return type of the call. 129 @param ret_is_list: whether the return type is an ApiList. 130 @param data: Optional data to send as payload to the call. 131 @param params: Optional query parameters for the call. 132 @param api_version: minimum API version for the call. 133 """ 134 check_api_version(method.im_self, api_version) 135 if data is not None: 136 data = json.dumps(Attr(is_api_list=True).to_json(data, False)) 137 ret = method(path, data=data, params=params) 138 else: 139 ret = method(path, params=params) 140 if ret_type is None: 141 return 142 elif ret_is_list: 143 return ApiList.from_json_dict(ret, method.im_self, ret_type) 144 elif isinstance(ret, list): 145 return [ ret_type.from_json_dict(x, method.im_self) for x in ret ] 146 else: 147 return ret_type.from_json_dict(ret, method.im_self)
148
149 -class BaseApiObject(object):
150 """ 151 The BaseApiObject helps with (de)serialization from/to JSON. 152 153 The derived class has two ways of defining custom attributes: 154 - Overwriting the '_ATTRIBUTES' field with the attribute dictionary 155 - Override the _get_attributes() method, in case static initialization of 156 the above field is not possible. 157 158 It's recommended that the _get_attributes() implementation do caching to 159 avoid computing the dictionary on every invocation. 160 161 The derived class's constructor must call the base class's init() static 162 method. All constructor arguments (aside from self and resource_root) must 163 be keywords arguments with default values (typically None), or 164 from_json_dict() will not work. 165 """ 166 167 _ATTRIBUTES = { } 168 _WHITELIST = ( '_resource_root', '_attributes' ) 169 170 @classmethod
171 - def _get_attributes(cls):
172 """ 173 Returns a map of property names to attr instances (or None for default 174 attribute behavior) describing the properties of the object. 175 176 By default, this method will return the class's _ATTRIBUTES field. 177 Classes can override this method to do custom initialization of the 178 attributes when needed. 179 """ 180 return cls._ATTRIBUTES
181 182 @staticmethod
183 - def init(obj, resource_root, attrs=None):
184 """ 185 Wraper around the real constructor to avoid issues with the 'self' 186 argument. Call like this, from a subclass's constructor: 187 188 - BaseApiObject.init(self, locals()) 189 """ 190 # This works around http://bugs.python.org/issue2646 191 # We use unicode strings as keys in kwargs. 192 str_attrs = { } 193 if attrs: 194 for k, v in attrs.iteritems(): 195 if k not in ('self', 'resource_root'): 196 str_attrs[k] = v 197 BaseApiObject.__init__(obj, resource_root, **str_attrs)
198
199 - def __init__(self, resource_root, **attrs):
200 """ 201 Initializes internal state and sets all known writable properties of the 202 object to None. Then initializes the properties given in the provided 203 attributes dictionary. 204 205 @param resource_root: API resource object. 206 @param attrs: optional dictionary of attributes to set. This should only 207 contain r/w attributes. 208 """ 209 self._resource_root = resource_root 210 211 for name, attr in self._get_attributes().iteritems(): 212 object.__setattr__(self, name, None) 213 if attrs: 214 self._set_attrs(attrs, from_json=False)
215
216 - def _set_attrs(self, attrs, allow_ro=False, from_json=True):
217 """ 218 Sets all the attributes in the dictionary. Optionally, allows setting 219 read-only attributes (e.g. when deserializing from JSON) and skipping 220 JSON deserialization of values. 221 """ 222 for k, v in attrs.iteritems(): 223 attr = self._check_attr(k, allow_ro) 224 if attr and from_json: 225 v = attr.from_json(self._get_resource_root(), v) 226 object.__setattr__(self, k, v)
227
228 - def __setattr__(self, name, val):
229 if name not in BaseApiObject._WHITELIST: 230 self._check_attr(name, False) 231 object.__setattr__(self, name, val)
232
233 - def _check_attr(self, name, allow_ro):
234 if name not in self._get_attributes(): 235 raise AttributeError('Invalid property %s for class %s.' % 236 (name, self.__class__.__name__)) 237 attr = self._get_attributes()[name] 238 if not allow_ro and attr and not attr.rw: 239 raise AttributeError('Attribute %s of class %s is read only.' % 240 (name, self.__class__.__name__)) 241 return attr
242
243 - def _get_resource_root(self):
244 return self._resource_root
245
246 - def _update(self, api_obj):
247 """Copy state from api_obj to this object.""" 248 if not isinstance(self, api_obj.__class__): 249 raise ValueError( 250 "Class %s does not derive from %s; cannot update attributes." % 251 (self.__class__, api_obj.__class__)) 252 253 for name in self._get_attributes().keys(): 254 try: 255 val = getattr(api_obj, name) 256 setattr(self, name, val) 257 except AttributeError, ignored: 258 pass
259
260 - def to_json_dict(self, preserve_ro=False):
261 dic = { } 262 for name, attr in self._get_attributes().iteritems(): 263 if not preserve_ro and attr and not attr.rw: 264 continue 265 try: 266 value = getattr(self, name) 267 if value is not None: 268 if attr: 269 dic[name] = attr.to_json(value, preserve_ro) 270 else: 271 dic[name] = value 272 except AttributeError: 273 pass 274 return dic
275
276 - def __str__(self):
277 """ 278 Default implementation of __str__. Uses the type name and the first 279 attribute retrieved from the attribute map to create the string. 280 """ 281 name = self._get_attributes().keys()[0] 282 value = getattr(self, name, None) 283 return "<%s>: %s = %s" % (self.__class__.__name__, name, value)
284 285 @classmethod
286 - def from_json_dict(cls, dic, resource_root):
287 obj = cls(resource_root) 288 obj._set_attrs(dic, allow_ro=True) 289 return obj
290
291 -class BaseApiResource(BaseApiObject):
292 """ 293 A specialization of BaseApiObject that provides some utility methods for 294 resources. This class allows easier serialization / deserialization of 295 parameters and return values. 296 """ 297
298 - def _api_version(self):
299 """ 300 Returns the minimum API version for this resource. Defaults to 1. 301 """ 302 return 1
303
304 - def _path(self):
305 """ 306 Returns the path to the resource. 307 308 e.g., for a service 'foo' in cluster 'bar', this should return 309 '/clusters/bar/services/foo'. 310 """ 311 raise NotImplementedError
312
313 - def _require_min_api_version(self, version):
314 """ 315 Raise an exception if the version of the api is less than the given version. 316 317 @param version: The minimum required version. 318 """ 319 actual_version = self._get_resource_root().version 320 version = max(version, self._api_version()) 321 if actual_version < version: 322 raise Exception("API version %s is required but %s is in use." 323 % (version, actual_version))
324
325 - def _cmd(self, command, data=None, params=None, api_version=1):
326 """ 327 Invokes a command on the resource. Commands are expected to be under the 328 "commands/" sub-resource. 329 """ 330 return self._post("commands/" + command, ApiCommand, 331 data=data, params=params, api_version=api_version)
332
333 - def _get_config(self, rel_path, view, api_version=1):
334 """ 335 Retrieves an ApiConfig list from the given relative path. 336 """ 337 self._require_min_api_version(api_version) 338 params = view and dict(view=view) or None 339 resp = self._get_resource_root().get(self._path() + '/' + rel_path, 340 params=params) 341 return json_to_config(resp, view == 'full')
342
343 - def _update_config(self, rel_path, config, api_version=1):
344 self._require_min_api_version(api_version) 345 resp = self._get_resource_root().put(self._path() + '/' + rel_path, 346 data=config_to_json(config)) 347 return json_to_config(resp, False)
348
349 - def _delete(self, rel_path, ret_type, ret_is_list=False, params=None, 350 api_version=1):
351 return self._call('delete', rel_path, ret_type, ret_is_list, None, params, 352 api_version)
353
354 - def _get(self, rel_path, ret_type, ret_is_list=False, params=None, 355 api_version=1):
356 return self._call('get', rel_path, ret_type, ret_is_list, None, params, 357 api_version)
358
359 - def _post(self, rel_path, ret_type, ret_is_list=False, data=None, params=None, 360 api_version=1):
361 return self._call('post', rel_path, ret_type, ret_is_list, data, params, 362 api_version)
363
364 - def _put(self, rel_path, ret_type, ret_is_list=False, data=None, params=None, 365 api_version=1):
366 return self._call('put', rel_path, ret_type, ret_is_list, data, params, 367 api_version)
368
369 - def _call(self, method, rel_path, ret_type, ret_is_list=False, data=None, 370 params=None, api_version=1):
371 path = self._path() 372 if rel_path: 373 path += '/' + rel_path 374 return call(getattr(self._get_resource_root(), method), 375 path, 376 ret_type, 377 ret_is_list, 378 data, 379 params, 380 api_version)
381
382 -class ApiList(BaseApiObject):
383 """A list of some api object""" 384 LIST_KEY = "items" 385
386 - def __init__(self, objects, resource_root=None, **attrs):
387 BaseApiObject.__init__(self, resource_root, **attrs) 388 # Bypass checks in BaseApiObject.__setattr__ 389 object.__setattr__(self, 'objects', objects)
390
391 - def __str__(self):
392 return "<ApiList>(%d): [%s]" % ( 393 len(self.objects), 394 ", ".join([str(item) for item in self.objects]))
395
396 - def to_json_dict(self, preserve_ro=False):
397 ret = BaseApiObject.to_json_dict(self, preserve_ro) 398 attr = Attr() 399 ret[ApiList.LIST_KEY] = [ attr.to_json(x, preserve_ro) for x in self.objects ] 400 return ret
401
402 - def __len__(self):
403 return self.objects.__len__()
404
405 - def __iter__(self):
406 return self.objects.__iter__()
407
408 - def __getitem__(self, i):
409 return self.objects.__getitem__(i)
410
411 - def __getslice(self, i, j):
412 return self.objects.__getslice__(i, j)
413 414 @classmethod
415 - def from_json_dict(cls, dic, resource_root, member_cls=None):
416 if not member_cls: 417 member_cls = cls._MEMBER_CLASS 418 attr = Attr(atype=member_cls) 419 items = [] 420 if ApiList.LIST_KEY in dic: 421 items = [ attr.from_json(resource_root, x) for x in dic[ApiList.LIST_KEY] ] 422 ret = cls(items) 423 # If the class declares custom attributes, populate them based on the input 424 # dict. The check avoids extra overhead for the common case, where we just 425 # have a plain list. _set_attrs() also does not understand the "items" 426 # attribute, so it can't be in the input data. 427 if cls._ATTRIBUTES: 428 if ApiList.LIST_KEY in dic: 429 dic = copy.copy(dic) 430 del dic[ApiList.LIST_KEY] 431 ret._set_attrs(dic, allow_ro=True) 432 return ret
433
434 -class ApiHostRef(BaseApiObject):
435 _ATTRIBUTES = { 436 'hostId' : None, 437 } 438
439 - def __init__(self, resource_root, hostId=None):
440 BaseApiObject.init(self, resource_root, locals())
441
442 - def __str__(self):
443 return "<ApiHostRef>: %s" % (self.hostId)
444
445 -class ApiServiceRef(BaseApiObject):
446 _ATTRIBUTES = { 447 'clusterName' : None, 448 'serviceName' : None, 449 'peerName' : None, 450 } 451
452 - def __init__(self, resource_root, serviceName=None, clusterName=None, 453 peerName=None):
454 BaseApiObject.init(self, resource_root, locals())
455
456 -class ApiClusterRef(BaseApiObject):
457 _ATTRIBUTES = { 458 'clusterName' : None, 459 } 460
461 - def __init__(self, resource_root, clusterName = None):
462 BaseApiObject.init(self, resource_root, locals())
463
464 -class ApiRoleRef(BaseApiObject):
465 _ATTRIBUTES = { 466 'clusterName' : None, 467 'serviceName' : None, 468 'roleName' : None, 469 } 470
471 - def __init__(self, resource_root, serviceName=None, roleName=None, 472 clusterName=None):
473 BaseApiObject.init(self, resource_root, locals())
474
475 -class ApiRoleConfigGroupRef(BaseApiObject):
476 _ATTRIBUTES = { 477 'roleConfigGroupName' : None, 478 } 479
480 - def __init__(self, resource_root, roleConfigGroupName=None):
481 BaseApiObject.init(self, resource_root, locals())
482
483 -class ApiCommand(BaseApiObject):
484 SYNCHRONOUS_COMMAND_ID = -1 485 486 @classmethod
487 - def _get_attributes(cls):
488 if not cls.__dict__.has_key('_ATTRIBUTES'): 489 cls._ATTRIBUTES = { 490 'id' : ROAttr(), 491 'name' : ROAttr(), 492 'startTime' : ROAttr(datetime.datetime), 493 'endTime' : ROAttr(datetime.datetime), 494 'active' : ROAttr(), 495 'success' : ROAttr(), 496 'resultMessage' : ROAttr(), 497 'clusterRef' : ROAttr(ApiClusterRef), 498 'serviceRef' : ROAttr(ApiServiceRef), 499 'roleRef' : ROAttr(ApiRoleRef), 500 'hostRef' : ROAttr(ApiHostRef), 501 'children' : ROAttr(ApiCommand, is_api_list=True), 502 'parent' : ROAttr(ApiCommand), 503 'resultDataUrl' : ROAttr(), 504 'canRetry' : ROAttr(), 505 } 506 return cls._ATTRIBUTES
507
508 - def __str__(self):
509 return "<ApiCommand>: '%s' (id: %s; active: %s; success: %s)" % ( 510 self.name, self.id, self.active, self.success)
511
512 - def _path(self):
513 return '/commands/%d' % self.id
514
515 - def fetch(self):
516 """ 517 Retrieve updated data about the command from the server. 518 519 @return: A new ApiCommand object. 520 """ 521 if self.id == ApiCommand.SYNCHRONOUS_COMMAND_ID: 522 return self 523 524 resp = self._get_resource_root().get(self._path()) 525 return ApiCommand.from_json_dict(resp, self._get_resource_root())
526
527 - def wait(self, timeout=None):
528 """ 529 Wait for command to finish. 530 531 @param timeout: (Optional) Max amount of time (in seconds) to wait. Wait 532 forever by default. 533 @return: The final ApiCommand object, containing the last known state. 534 The command may still be running in case of timeout. 535 """ 536 if self.id == ApiCommand.SYNCHRONOUS_COMMAND_ID: 537 return self 538 539 SLEEP_SEC = 5 540 541 if timeout is None: 542 deadline = None 543 else: 544 deadline = time.time() + timeout 545 546 while True: 547 cmd = self.fetch() 548 if not cmd.active: 549 return cmd 550 551 if deadline is not None: 552 now = time.time() 553 if deadline < now: 554 return cmd 555 else: 556 time.sleep(min(SLEEP_SEC, deadline - now)) 557 else: 558 time.sleep(SLEEP_SEC)
559 560
561 - def abort(self):
562 """ 563 Abort a running command. 564 565 @return: A new ApiCommand object with the updated information. 566 """ 567 if self.id == ApiCommand.SYNCHRONOUS_COMMAND_ID: 568 return self 569 570 path = self._path() + '/abort' 571 resp = self._get_resource_root().post(path) 572 return ApiCommand.from_json_dict(resp, self._get_resource_root())
573
574 - def retry(self):
575 """ 576 Retry a failed or aborted command. 577 578 @return: A new ApiCommand object with the updated information. 579 """ 580 path = self._path() + '/retry' 581 resp = self._get_resource_root().post(path) 582 return ApiCommand.from_json_dict(resp, self._get_resource_root())
583
584 -class ApiBulkCommandList(ApiList):
585 _ATTRIBUTES = { 586 'errors' : ROAttr(), 587 } 588 _MEMBER_CLASS = ApiCommand
589
590 -class ApiCommandMetadata(BaseApiObject):
591 _ATTRIBUTES = { 592 'name' : ROAttr(), 593 'argSchema' : ROAttr(), 594 } 595
596 - def __init__(self, resource_root):
597 BaseApiObject.init(self, resource_root)
598
599 - def __str__(self):
600 return "<ApiCommandMetadata>: %s (%s)" % (self.name, self.argSchema)
601
602 # 603 # Metrics. 604 # 605 606 -class ApiMetricData(BaseApiObject):
607 """Metric reading data.""" 608 609 _ATTRIBUTES = { 610 'timestamp' : ROAttr(datetime.datetime), 611 'value' : ROAttr(), 612 } 613
614 - def __init__(self, resource_root):
615 BaseApiObject.init(self, resource_root)
616
617 618 -class ApiMetric(BaseApiObject):
619 """Metric information.""" 620 621 _ATTRIBUTES = { 622 'name' : ROAttr(), 623 'context' : ROAttr(), 624 'unit' : ROAttr(), 625 'data' : ROAttr(ApiMetricData), 626 'displayName' : ROAttr(), 627 'description' : ROAttr(), 628 } 629
630 - def __init__(self, resource_root):
631 BaseApiObject.init(self, resource_root)
632
633 # 634 # Activities. 635 # 636 637 -class ApiActivity(BaseApiObject):
638 _ATTRIBUTES = { 639 'name' : ROAttr(), 640 'type' : ROAttr(), 641 'parent' : ROAttr(), 642 'startTime' : ROAttr(), 643 'finishTime' : ROAttr(), 644 'id' : ROAttr(), 645 'status' : ROAttr(), 646 'user' : ROAttr(), 647 'group' : ROAttr(), 648 'inputDir' : ROAttr(), 649 'outputDir' : ROAttr(), 650 'mapper' : ROAttr(), 651 'combiner' : ROAttr(), 652 'reducer' : ROAttr(), 653 'queueName' : ROAttr(), 654 'schedulerPriority' : ROAttr(), 655 } 656
657 - def __init__(self, resource_root):
658 BaseApiObject.init(self, resource_root)
659
660 - def __str__(self):
661 return "<ApiActivity>: %s (%s)" % (self.name, self.status)
662
663 # 664 # Replication 665 # 666 667 -class ApiCmPeer(BaseApiObject):
668 _ATTRIBUTES = { 669 'name' : None, 670 'url' : None, 671 'username' : None, 672 'password' : None, 673 'type' : None, 674 'clouderaManagerCreatedUser' : None, 675 } 676
677 - def __str__(self):
678 return "<ApiPeer>: %s (%s)" % (self.name, self.url)
679
680 -class ApiLicensedFeatureUsage(BaseApiObject):
681 _ATTRIBUTES = { 682 'totals' : ROAttr(), 683 'clusters' : ROAttr(), 684 }
685
686 -class ApiReplicationDiagnosticsCollectionArgs(BaseApiObject):
687 _ATTRIBUTES = { 688 'commands' : ROAttr(), 689 'ticketNumber' : ROAttr(), 690 'comments' : ROAttr(), 691 'phoneHome' : ROAttr(), 692 }
693
694 -class ApiHdfsReplicationArguments(BaseApiObject):
695 _ATTRIBUTES = { 696 'sourceService' : Attr(ApiServiceRef), 697 'sourcePath' : None, 698 'destinationPath' : None, 699 'mapreduceServiceName' : None, 700 'userName' : None, 701 'sourceUser' : None, 702 'numMaps' : None, 703 'dryRun' : None, 704 'bandwidthPerMap' : None, 705 'logPath' : None, 706 'schedulerPoolName' : None, 707 'abortOnError' : None, 708 'preservePermissions' : None, 709 'preserveBlockSize' : None, 710 'preserveReplicationCount' : None, 711 'removeMissingFiles' : None, 712 'skipChecksumChecks' : None, 713 'skipListingChecksumChecks' : None, 714 'skipTrash' : None, 715 'replicationStrategy' : None, 716 'preserveXAttrs' : None, 717 'exclusionFilters' : None, 718 }
719
720 -class ApiHdfsCloudReplicationArguments(ApiHdfsReplicationArguments):
721 @classmethod
722 - def _get_attributes(cls):
723 if not cls.__dict__.has_key('_ATTRIBUTES'): 724 attrs = { 725 'sourceAccount' : None, 726 'destinationAccount' : None, 727 } 728 attrs.update(ApiHdfsReplicationArguments._get_attributes()) 729 cls._ATTRIBUTES = attrs 730 return cls._ATTRIBUTES
731
732 -class ApiHdfsReplicationResult(BaseApiObject):
733 _ATTRIBUTES = { 734 'progress' : ROAttr(), 735 'counters' : ROAttr(), 736 'numBytesDryRun' : ROAttr(), 737 'numFilesDryRun' : ROAttr(), 738 'numFilesExpected' : ROAttr(), 739 'numBytesExpected' : ROAttr(), 740 'numFilesCopied' : ROAttr(), 741 'numBytesCopied' : ROAttr(), 742 'numFilesSkipped' : ROAttr(), 743 'numBytesSkipped' : ROAttr(), 744 'numFilesDeleted' : ROAttr(), 745 'numFilesCopyFailed' : ROAttr(), 746 'numBytesCopyFailed' : ROAttr(), 747 'setupError' : ROAttr(), 748 'jobId' : ROAttr(), 749 'jobDetailsUri' : ROAttr(), 750 'dryRun' : ROAttr(), 751 'snapshottedDirs' : ROAttr(), 752 'failedFiles' : ROAttr(), 753 'runAsUser' : ROAttr(), 754 'runOnSourceAsUser' : ROAttr(), 755 }
756
757 -class ApiHiveTable(BaseApiObject):
758 _ATTRIBUTES = { 759 'database' : None, 760 'tableName' : None, 761 } 762
763 - def __str__(self):
764 return "<ApiHiveTable>: %s, %s" % (self.database, self.tableName)
765
766 -class ApiImpalaUDF(BaseApiObject):
767 _ATTRIBUTES = { 768 'database' : ROAttr(), 769 'signature' : ROAttr(), 770 } 771
772 - def __str__(self):
773 return "<ApiImpalaUDF>: %s, %s" % (self.database, self.signature)
774
775 -class ApiHiveUDF(BaseApiObject):
776 _ATTRIBUTES = { 777 'database' : ROAttr(), 778 'signature' : ROAttr(), 779 } 780
781 - def __str__(self):
782 return "<ApiHiveUDF>: %s, %s" % (self.database, self.signature)
783
784 -class ApiHiveReplicationArguments(BaseApiObject):
785 _ATTRIBUTES = { 786 'sourceService' : Attr(ApiServiceRef), 787 'tableFilters' : Attr(ApiHiveTable), 788 'exportDir' : None, 789 'force' : None, 790 'replicateData' : None, 791 'hdfsArguments' : Attr(ApiHdfsReplicationArguments), 792 'dryRun' : None, 793 'replicateImpalaMetadata' : None, 794 }
795
796 -class ApiHiveReplicationResult(BaseApiObject):
797 _ATTRIBUTES = { 798 'tableCount' : ROAttr(), 799 'tables' : ROAttr(ApiHiveTable), 800 'impalaUDFCount' : ROAttr(), 801 'impalaUDFs' : ROAttr(ApiImpalaUDF), 802 'hiveUDFCount' : ROAttr(), 803 'hiveUDFs' : ROAttr(ApiHiveUDF), 804 'errorCount' : ROAttr(), 805 'errors' : ROAttr(), 806 'dataReplicationResult' : ROAttr(ApiHdfsReplicationResult), 807 'dryRun' : ROAttr(), 808 'runAsUser' : ROAttr(), 809 'runOnSourceAsUser' : ROAttr(), 810 'phase' : ROAttr(), 811 }
812
813 -class ApiReplicationCommand(ApiCommand):
814 @classmethod
815 - def _get_attributes(cls):
816 if not cls.__dict__.has_key('_ATTRIBUTES'): 817 attrs = { 818 'hdfsResult' : ROAttr(ApiHdfsReplicationResult), 819 'hiveResult' : ROAttr(ApiHiveReplicationResult), 820 } 821 attrs.update(ApiCommand._get_attributes()) 822 cls._ATTRIBUTES = attrs 823 return cls._ATTRIBUTES
824
825 -class ApiReplicationSchedule(BaseApiObject):
826 _ATTRIBUTES = { 827 'startTime' : Attr(datetime.datetime), 828 'endTime' : Attr(datetime.datetime), 829 'interval' : None, 830 'intervalUnit' : None, 831 'paused' : None, 832 'hdfsArguments' : Attr(ApiHdfsReplicationArguments), 833 'hiveArguments' : Attr(ApiHiveReplicationArguments), 834 'hdfsCloudArguments' : Attr(ApiHdfsCloudReplicationArguments), 835 'alertOnStart' : None, 836 'alertOnSuccess' : None, 837 'alertOnFail' : None, 838 'alertOnAbort' : None, 839 'id' : ROAttr(), 840 'nextRun' : ROAttr(datetime.datetime), 841 'history' : ROAttr(ApiReplicationCommand), 842 'active' : None 843 }
844
845 -class ApiHBaseSnapshotPolicyArguments(BaseApiObject):
846 _ATTRIBUTES = { 847 'tableRegExps' : None, 848 'storage' : None, 849 }
850
851 -class ApiHdfsSnapshotPolicyArguments(BaseApiObject):
852 _ATTRIBUTES = { 853 'pathPatterns' : None, 854 }
855
856 -class ApiHBaseSnapshot(BaseApiObject):
857 _ATTRIBUTES = { 858 'snapshotName' : None, 859 'tableName' : None, 860 'creationTime' : ROAttr(datetime.datetime), 861 'storage' : None, 862 }
863
864 -class ApiHBaseSnapshotError(BaseApiObject):
865 _ATTRIBUTES = { 866 'tableName' : ROAttr(), 867 'snapshotName' : ROAttr(), 868 'error' : ROAttr(), 869 'storage' : ROAttr(), 870 }
871
872 -class ApiHdfsSnapshot(BaseApiObject):
873 _ATTRIBUTES = { 874 'path' : None, 875 'snapshotName' : None, 876 'snapshotPath' : None, 877 'creationTime' : ROAttr(datetime.datetime), 878 }
879
880 -class ApiHdfsSnapshotError(BaseApiObject):
881 _ATTRIBUTES = { 882 'path' : ROAttr(), 883 'snapshotName' : ROAttr(), 884 'snapshotPath' : ROAttr(), 885 'error' : ROAttr(), 886 }
887
888 -class ApiHBaseSnapshotResult(BaseApiObject):
889 _ATTRIBUTES = { 890 'processedTableCount' : ROAttr(), 891 'processedTables' : ROAttr(), 892 'unprocessedTableCount' : ROAttr(), 893 'unprocessedTables' : ROAttr(), 894 'createdSnapshotCount' : ROAttr(), 895 'createdSnapshots' : ROAttr(ApiHBaseSnapshot), 896 'deletedSnapshotCount' : ROAttr(), 897 'deletedSnapshots' : ROAttr(ApiHBaseSnapshot), 898 'creationErrorCount' : ROAttr(), 899 'creationErrors' : ROAttr(ApiHBaseSnapshotError), 900 'deletionErrorCount' : ROAttr(), 901 'deletionErrors' : ROAttr(ApiHBaseSnapshotError), 902 }
903
904 -class ApiHdfsSnapshotResult(BaseApiObject):
905 _ATTRIBUTES = { 906 'processedPathCount' : ROAttr(), 907 'processedPaths' : ROAttr(), 908 'unprocessedPathCount' : ROAttr(), 909 'unprocessedPaths' : ROAttr(), 910 'createdSnapshotCount' : ROAttr(), 911 'createdSnapshots' : ROAttr(ApiHdfsSnapshot), 912 'deletedSnapshotCount' : ROAttr(), 913 'deletedSnapshots' : ROAttr(ApiHdfsSnapshot), 914 'creationErrorCount' : ROAttr(), 915 'creationErrors' : ROAttr(ApiHdfsSnapshotError), 916 'deletionErrorCount' : ROAttr(), 917 'deletionErrors' : ROAttr(ApiHdfsSnapshotError), 918 }
919
920 -class ApiSnapshotCommand(BaseApiObject):
921 @classmethod
922 - def _get_attributes(cls):
923 if not cls.__dict__.has_key('_ATTRIBUTES'): 924 attrs = { 925 'hdfsResult' : ROAttr(ApiHdfsSnapshotResult), 926 'hbaseResult' : ROAttr(ApiHBaseSnapshotResult), 927 } 928 attrs.update(ApiCommand._get_attributes()) 929 cls._ATTRIBUTES = attrs 930 return cls._ATTRIBUTES
931
932 -class ApiSnapshotPolicy(BaseApiObject):
933 """ 934 @type name: str 935 @ivar name: Name of the snapshot policy. 936 @type description: str 937 @ivar description: Description of the snapshot policy. 938 @type hourly_snapshots: int 939 @ivar hourly_snapshots: Number of hourly snapshots to be retained (default: 0). 940 @type daily_snapshots: int 941 @ivar daily_snapshots: Number of daily snapshots to be retained (default: 0). 942 @type weekly_snapshots: int 943 @ivar weekly_snapshots: Number of weekly snapshots to be retained (default: 0). 944 @type monthly_snapshots: int 945 @ivar monthly_snapshots: Number of monthly snapshots to be retained (default: 0). 946 @type yearly_snapshots: int 947 @ivar yearly_snapshots: Number of yearly snapshots to be retained (default: 0). 948 @type hours_for_hourly_snapshots: list of int 949 @ivar hours_for_hourly_snapshots: Hours of the day that hourly snapshots should be created. 950 Valid values are 0 to 23. If this list is empty, then hourly snapshots are 951 created for every hour. 952 @type minute_of_hour: int 953 @ivar minute_of_hour: Minute in the hour that hourly, daily, weekly, monthly and yearly 954 snapshots should be created. Valid values are 0 to 59 (default: 0). 955 @type hour_of_day: int 956 @ivar hour_of_day: Hour in the day that daily, weekly, monthly and yearly snapshots should be created. 957 Valid values are 0 to 23 (default: 0). 958 @type day_of_week: int 959 @ivar day_of_week: Day of the week that weekly snapshots should be created. 960 Valid values are 1 to 7, 1 representing Sunday (default: 1). 961 @type day_of_month: int 962 @ivar day_of_month: Day of the month that monthly and yearly snapshots should be created. 963 Values from 1 to 31 are allowed. Additionally 0 to -30 can be used to 964 specify offsets from the last day of the month (default: 1). 965 @type month_of_year: int 966 @ivar month_of_year: Month of the year that yearly snapshots should be created. 967 Valid values are 1 to 12, 1 representing January (default: 1). 968 @ivar alert_on_start: whether to generate alerts on start of snapshot creation/deletion activity. 969 @ivar alert_on_success: whether to generate alerts on successful completion of snapshot creation/deletion activity. 970 @ivar alert_on_fail: whether to generate alerts on failure of snapshot creation/deletion activity. 971 @ivar alert_on_abort: whether to generate alerts on abort of snapshot creation/deletion activity. 972 @ivar paused: whether to run the policy on schedule 973 @type hbaseArguments: ApiHBaseSnapshotPolicyArguments 974 @ivar hbaseArguments: HBase specific arguments for the replication job. 975 @type hdfsArguments: ApiHdfsSnapshotPolicyArguments 976 @ivar hdfsArguments: HDFS specific arguments for the replication job. 977 """ 978 _ATTRIBUTES = { 979 'name' : None, 980 'description' : None, 981 'hourlySnapshots' : None, 982 'dailySnapshots' : None, 983 'weeklySnapshots' : None, 984 'monthlySnapshots' : None, 985 'yearlySnapshots' : None, 986 'minuteOfHour' : None, 987 'hourOfDay' : None, 988 'dayOfWeek' : None, 989 'dayOfMonth' : None, 990 'monthOfYear' : None, 991 'hoursForHourlySnapshots' : None, 992 'alertOnStart' : None, 993 'alertOnSuccess' : None, 994 'alertOnFail' : None, 995 'alertOnAbort' : None, 996 'paused' : None, 997 'hbaseArguments' : Attr(ApiHBaseSnapshotPolicyArguments), 998 'hdfsArguments' : Attr(ApiHdfsSnapshotPolicyArguments), 999 'lastCommand' : ROAttr(ApiSnapshotCommand), 1000 'lastSuccessfulCommand' : ROAttr(ApiSnapshotCommand), 1001 }
1002
1003 # 1004 # Batch. 1005 # 1006 1007 -class ApiBatchRequestElement(BaseApiObject):
1008 """One element in a batch request.""" 1009 _ATTRIBUTES = { 1010 'method' : None, 1011 'url' : None, 1012 'body' : None, 1013 'contentType' : None, 1014 'acceptType' : None, 1015 }
1016
1017 -class ApiBatchResponseElement(BaseApiObject):
1018 """One element in a batch response.""" 1019 _ATTRIBUTES = { 1020 'statusCode' : ROAttr(), 1021 'response' : ROAttr(), 1022 }
1023
1024 -class ApiBatchResponseList(ApiList):
1025 """A list of batch response objects.""" 1026 _ATTRIBUTES = { 1027 'success' : ROAttr(), 1028 } 1029 _MEMBER_CLASS = ApiBatchResponseElement
1030
1031 # 1032 # Configuration helpers. 1033 # 1034 1035 -class ApiConfig(BaseApiObject):
1036 _ATTRIBUTES = { 1037 'name' : None, 1038 'value' : None, 1039 'required' : ROAttr(), 1040 'default' : ROAttr(), 1041 'displayName' : ROAttr(), 1042 'description' : ROAttr(), 1043 'relatedName' : ROAttr(), 1044 'sensitive' : ROAttr(), 1045 'validationState' : ROAttr(), 1046 'validationMessage' : ROAttr(), 1047 'validationWarningsSuppressed' : ROAttr() 1048 } 1049
1050 - def __init__(self, resource_root, name=None, value=None):
1051 BaseApiObject.init(self, resource_root, locals())
1052
1053 - def __str__(self):
1054 return "<ApiConfig>: %s = %s" % (self.name, self.value)
1055
1056 -class ApiImpalaQuery(BaseApiObject):
1057 _ATTRIBUTES = { 1058 'queryId' : ROAttr(), 1059 'queryState' : ROAttr(), 1060 'queryType' : ROAttr(), 1061 'statement' : ROAttr(), 1062 'database' : ROAttr(), 1063 'rowsProduced' : ROAttr(), 1064 'coordinator' : ROAttr(ApiHostRef), 1065 'user' : ROAttr(), 1066 'startTime' : ROAttr(datetime.datetime), 1067 'endTime' : ROAttr(datetime.datetime), 1068 'detailsAvailable' : ROAttr(), 1069 'attributes' : ROAttr(), 1070 'durationMillis' : ROAttr() 1071 } 1072
1073 - def __str__(self):
1074 return "<ApiImpalaQuery>: %s" % (self.queryId)
1075
1076 # 1077 # WatchedDirectories data types 1078 # 1079 1080 -class ApiWatchedDir(BaseApiObject):
1081 1082 _ATTRIBUTES = { 1083 'path' : None 1084 } 1085
1086 - def __str__(self):
1087 return "<ApiWatchedDir>: %s" % (self.path)
1088
1089 -class ApiWatchedDirList(ApiList):
1090 1091 _ATTRIBUTES = { 1092 'watchedDirs' : ROAttr(ApiWatchedDir) 1093 } 1094 _MEMBER_CLASS = ApiWatchedDir
1095
1096 -class ApiImpalaQueryResponse(BaseApiObject):
1097 1098 _ATTRIBUTES = { 1099 'queries' : ROAttr(ApiImpalaQuery), 1100 'warnings' : ROAttr() 1101 }
1102
1103 -class ApiImpalaQueryDetailsResponse(BaseApiObject):
1104 _ATTRIBUTES = { 1105 'details' : ROAttr() 1106 } 1107
1108 - def __str__(self):
1109 return "<AipImpalaQueryDetailsResponse> %s" % self.details
1110
1111 -class ApiImpalaCancelResponse(BaseApiObject):
1112 _ATTRIBUTES = { 1113 'warning' : ROAttr() 1114 } 1115
1116 - def __str__(self):
1117 return "<ApiImpalaCancelResponse> %s" % self.warning
1118
1119 -class ApiImpalaQueryAttribute(BaseApiObject):
1120 1121 _ATTRIBUTES = { 1122 'name' : ROAttr(), 1123 'type' : ROAttr(), 1124 'displayName' : ROAttr(), 1125 'supportsHistograms' : ROAttr(), 1126 'description' : ROAttr() 1127 } 1128
1129 - def __str__(self):
1130 return "<ApiImpalaQueryAttribute> %s" % name
1131
1132 -class ApiMr2AppInformation(BaseApiObject):
1133 _ATTRIBUTES = { 1134 'jobState' : ROAttr() 1135 } 1136
1137 - def __str__(self):
1138 return "<ApiMr2AppInformation>: %s" % (self.jobState)
1139
1140 -class ApiYarnApplication(BaseApiObject):
1141 _ATTRIBUTES = { 1142 'applicationId' : ROAttr(), 1143 'name' : ROAttr(), 1144 'user' : ROAttr(), 1145 'startTime' : ROAttr(datetime.datetime), 1146 'endTime' : ROAttr(datetime.datetime), 1147 'pool' : ROAttr(), 1148 'state' : ROAttr(), 1149 'progress' : ROAttr(), 1150 'mr2AppInformation' : ROAttr(ApiMr2AppInformation), 1151 'attributes' : ROAttr(), 1152 'allocatedMB' : ROAttr(), 1153 'allocatedVCores' : ROAttr(), 1154 'runningContainers' : ROAttr(), 1155 'applicationTags' : ROAttr(), 1156 'allocatedMemorySeconds' : ROAttr(), 1157 'allocatedVcoreSeconds' : ROAttr(), 1158 'containerUsedMemorySeconds' : ROAttr(), 1159 'containerUsedCpuSeconds' : ROAttr(), 1160 'containerUsedVcoreSeconds' : ROAttr(), 1161 'containerAllocatedMemorySeconds' : ROAttr(), 1162 'containerAllocatedVcoreSeconds' : ROAttr(), 1163 'containerUsedMemoryMax' : ROAttr(), 1164 } 1165
1166 - def __str__(self):
1167 return "<ApiYarnApplication>: %s" % (self.applicationId)
1168
1169 -class ApiYarnApplicationResponse(BaseApiObject):
1170 1171 _ATTRIBUTES = { 1172 'applications' : ROAttr(ApiYarnApplication), 1173 'warnings' : ROAttr() 1174 }
1175
1176 -class ApiYarnKillResponse(BaseApiObject):
1177 _ATTRIBUTES = { 1178 'warning' : ROAttr() 1179 } 1180
1181 - def __str__(self):
1182 return "<ApiYarnKillResponse> %s" % self.warning
1183
1184 -class ApiYarnApplicationAttribute(BaseApiObject):
1185 1186 _ATTRIBUTES = { 1187 'name' : ROAttr(), 1188 'type' : ROAttr(), 1189 'displayName' : ROAttr(), 1190 'supportsHistograms' : ROAttr(), 1191 'description' : ROAttr() 1192 } 1193
1194 - def __str__(self):
1195 return "<ApiYarnApplicationAttribute> %s" % name
1196
1197 -class ApiTimeSeriesRequest(BaseApiObject):
1198 _ATTRIBUTES = { 1199 'query' : None, 1200 'from' : None, 1201 'to' : None, 1202 'contentType' : None, 1203 'desiredRollup' : None, 1204 'mustUseDesiredRollup' : None 1205 } 1206
1207 - def __str__(self):
1208 return "<ApiTimeSeriesRequest>: %s" % (self.query)
1209
1210 -class ApiProductVersion(BaseApiObject):
1211 _ATTRIBUTES = { 1212 'version' : None, 1213 'product' : None, 1214 }
1215
1216 -class ApiClusterTemplateConfig(BaseApiObject):
1217 _ATTRIBUTES = { 1218 'name' : None, 1219 'value' : None, 1220 'ref' : None, 1221 'variable' : None, 1222 'autoConfig' : None, 1223 }
1224
1225 -class ApiClusterTemplateRoleConfigGroup(BaseApiObject):
1226 _ATTRIBUTES = { 1227 'refName' : None, 1228 'roleType' : None, 1229 'base' : None, 1230 'displayName' : None, 1231 'configs' : Attr(ApiClusterTemplateConfig), 1232 }
1233
1234 -class ApiClusterTemplateRole(BaseApiObject):
1235 _ATTRIBUTES = { 1236 'refName' : None, 1237 'roleType' : None, 1238 }
1239
1240 -class ApiClusterTemplateHostTemplate(BaseApiObject):
1241 _ATTRIBUTES = { 1242 'refName' : None, 1243 'cardinality' : None, 1244 'roleConfigGroupsRefNames' : None, 1245 }
1246
1247 -class ApiClusterTemplateHostInfo(BaseApiObject):
1248 _ATTRIBUTES = { 1249 'hostName' : None, 1250 'hostNameRange' : None, 1251 'rackId' : None, 1252 'hostTemplateRefName' : None, 1253 'roleRefNames' : None, 1254 }
1255
1256 -class ApiClusterTemplateVariable(BaseApiObject):
1257 _ATTRIBUTES = { 1258 'name' : None, 1259 'value' : None, 1260 }
1261
1262 -class ApiClusterTemplateRoleConfigGroupInfo(BaseApiObject):
1263 _ATTRIBUTES = { 1264 'rcgRefName' : None, 1265 'name' : None, 1266 }
1267
1268 -class ApiClusterTemplateInstantiator(BaseApiObject):
1269 _ATTRIBUTES = { 1270 'clusterName' : None, 1271 'hosts' : Attr(ApiClusterTemplateHostInfo), 1272 'variables' : Attr(ApiClusterTemplateVariable), 1273 'roleConfigGroups' : Attr(ApiClusterTemplateRoleConfigGroupInfo), 1274 }
1275
1276 -class ApiClusterTemplateService(BaseApiObject):
1277 _ATTRIBUTES = { 1278 'refName' : None, 1279 'serviceType' : None, 1280 'serviceConfigs' : Attr(ApiClusterTemplateConfig), 1281 'roleConfigGroups' : Attr(ApiClusterTemplateRoleConfigGroup), 1282 'displayName' : None, 1283 'roles' : Attr(ApiClusterTemplateRole), 1284 }
1285
1286 -class ApiClusterTemplate(BaseApiObject):
1287 _ATTRIBUTES = { 1288 'cdhVersion' : None, 1289 'displayName' : None, 1290 'cmVersion' : None, 1291 "repositories" : None, 1292 'products' : Attr(ApiProductVersion), 1293 'services' : Attr(ApiClusterTemplateService), 1294 'hostTemplates' : Attr(ApiClusterTemplateHostTemplate), 1295 'instantiator' : Attr(ApiClusterTemplateInstantiator), 1296 }
1297
1298 -def config_to_api_list(dic):
1299 """ 1300 Converts a python dictionary into a list containing the proper 1301 ApiConfig encoding for configuration data. 1302 1303 @param dic: Key-value pairs to convert. 1304 @return: JSON dictionary of an ApiConfig list (*not* an ApiList). 1305 """ 1306 config = [ ] 1307 for k, v in dic.iteritems(): 1308 config.append({ 'name' : k, 'value': v }) 1309 return { ApiList.LIST_KEY : config }
1310
1311 -def config_to_json(dic):
1312 """ 1313 Converts a python dictionary into a JSON payload. 1314 1315 The payload matches the expected "apiConfig list" type used to update 1316 configuration parameters using the API. 1317 1318 @param dic: Key-value pairs to convert. 1319 @return: String with the JSON-encoded data. 1320 """ 1321 return json.dumps(config_to_api_list(dic))
1322
1323 -def json_to_config(dic, full = False):
1324 """ 1325 Converts a JSON-decoded config dictionary to a python dictionary. 1326 1327 When materializing the full view, the values in the dictionary will be 1328 instances of ApiConfig, instead of strings. 1329 1330 @param dic: JSON-decoded config dictionary. 1331 @param full: Whether to materialize the full view of the config data. 1332 @return: Python dictionary with config data. 1333 """ 1334 config = { } 1335 for entry in dic['items']: 1336 k = entry['name'] 1337 if full: 1338 config[k] = ApiConfig.from_json_dict(entry, None) 1339 else: 1340 config[k] = entry.get('value') 1341 return config
1342