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 Note: The retry will only work for ClusterUpgrade command for now. 578 579 @return: A new ApiCommand object with the updated information. 580 """ 581 path = self._path() + '/retry' 582 resp = self._get_resource_root().post(path) 583 return ApiCommand.from_json_dict(resp, self._get_resource_root())
584
585 -class ApiBulkCommandList(ApiList):
586 _ATTRIBUTES = { 587 'errors' : ROAttr(), 588 } 589 _MEMBER_CLASS = ApiCommand
590
591 -class ApiCommandMetadata(BaseApiObject):
592 _ATTRIBUTES = { 593 'name' : ROAttr(), 594 'argSchema' : ROAttr(), 595 } 596
597 - def __init__(self, resource_root):
598 BaseApiObject.init(self, resource_root)
599
600 - def __str__(self):
601 return "<ApiCommandMetadata>: %s (%s)" % (self.name, self.argSchema)
602
603 # 604 # Metrics. 605 # 606 607 -class ApiMetricData(BaseApiObject):
608 """Metric reading data.""" 609 610 _ATTRIBUTES = { 611 'timestamp' : ROAttr(datetime.datetime), 612 'value' : ROAttr(), 613 } 614
615 - def __init__(self, resource_root):
616 BaseApiObject.init(self, resource_root)
617
618 619 -class ApiMetric(BaseApiObject):
620 """Metric information.""" 621 622 _ATTRIBUTES = { 623 'name' : ROAttr(), 624 'context' : ROAttr(), 625 'unit' : ROAttr(), 626 'data' : ROAttr(ApiMetricData), 627 'displayName' : ROAttr(), 628 'description' : ROAttr(), 629 } 630
631 - def __init__(self, resource_root):
632 BaseApiObject.init(self, resource_root)
633
634 # 635 # Activities. 636 # 637 638 -class ApiActivity(BaseApiObject):
639 _ATTRIBUTES = { 640 'name' : ROAttr(), 641 'type' : ROAttr(), 642 'parent' : ROAttr(), 643 'startTime' : ROAttr(), 644 'finishTime' : ROAttr(), 645 'id' : ROAttr(), 646 'status' : ROAttr(), 647 'user' : ROAttr(), 648 'group' : ROAttr(), 649 'inputDir' : ROAttr(), 650 'outputDir' : ROAttr(), 651 'mapper' : ROAttr(), 652 'combiner' : ROAttr(), 653 'reducer' : ROAttr(), 654 'queueName' : ROAttr(), 655 'schedulerPriority' : ROAttr(), 656 } 657
658 - def __init__(self, resource_root):
659 BaseApiObject.init(self, resource_root)
660
661 - def __str__(self):
662 return "<ApiActivity>: %s (%s)" % (self.name, self.status)
663
664 # 665 # Replication 666 # 667 668 -class ApiCmPeer(BaseApiObject):
669 _ATTRIBUTES = { 670 'name' : None, 671 'url' : None, 672 'username' : None, 673 'password' : None, 674 'type' : None, 675 'clouderaManagerCreatedUser' : None, 676 } 677
678 - def __str__(self):
679 return "<ApiPeer>: %s (%s)" % (self.name, self.url)
680
681 -class ApiLicensedFeatureUsage(BaseApiObject):
682 _ATTRIBUTES = { 683 'totals' : ROAttr(), 684 'clusters' : ROAttr(), 685 }
686
687 -class ApiHdfsReplicationArguments(BaseApiObject):
688 _ATTRIBUTES = { 689 'sourceService' : Attr(ApiServiceRef), 690 'sourcePath' : None, 691 'destinationPath' : None, 692 'mapreduceServiceName' : None, 693 'userName' : None, 694 'numMaps' : None, 695 'dryRun' : None, 696 'bandwidthPerMap' : None, 697 'logPath' : None, 698 'schedulerPoolName' : None, 699 'abortOnError' : None, 700 'preservePermissions' : None, 701 'preserveBlockSize' : None, 702 'preserveReplicationCount' : None, 703 'removeMissingFiles' : None, 704 'skipChecksumChecks' : None, 705 'skipTrash' : None, 706 'replicationStrategy' : None, 707 'preserveXAttrs' : None, 708 'exclusionFilters' : None, 709 }
710
711 -class ApiHdfsReplicationResult(BaseApiObject):
712 _ATTRIBUTES = { 713 'progress' : ROAttr(), 714 'counters' : ROAttr(), 715 'numBytesDryRun' : ROAttr(), 716 'numFilesDryRun' : ROAttr(), 717 'numFilesExpected' : ROAttr(), 718 'numBytesExpected' : ROAttr(), 719 'numFilesCopied' : ROAttr(), 720 'numBytesCopied' : ROAttr(), 721 'numFilesSkipped' : ROAttr(), 722 'numBytesSkipped' : ROAttr(), 723 'numFilesDeleted' : ROAttr(), 724 'numFilesCopyFailed' : ROAttr(), 725 'numBytesCopyFailed' : ROAttr(), 726 'setupError' : ROAttr(), 727 'jobId' : ROAttr(), 728 'jobDetailsUri' : ROAttr(), 729 'dryRun' : ROAttr(), 730 'snapshottedDirs' : ROAttr(), 731 'failedFiles' : ROAttr(), 732 'runAsUser' : ROAttr(), 733 }
734
735 -class ApiHiveTable(BaseApiObject):
736 _ATTRIBUTES = { 737 'database' : None, 738 'tableName' : None, 739 } 740
741 - def __str__(self):
742 return "<ApiHiveTable>: %s, %s" % (self.database, self.tableName)
743
744 -class ApiImpalaUDF(BaseApiObject):
745 _ATTRIBUTES = { 746 'database' : ROAttr(), 747 'signature' : ROAttr(), 748 } 749
750 - def __str__(self):
751 return "<ApiImpalaUDF>: %s, %s" % (self.database, self.signature)
752
753 -class ApiHiveReplicationArguments(BaseApiObject):
754 _ATTRIBUTES = { 755 'sourceService' : Attr(ApiServiceRef), 756 'tableFilters' : Attr(ApiHiveTable), 757 'exportDir' : None, 758 'force' : None, 759 'replicateData' : None, 760 'hdfsArguments' : Attr(ApiHdfsReplicationArguments), 761 'dryRun' : None, 762 'replicateImpalaMetadata' : None, 763 }
764
765 -class ApiHiveReplicationResult(BaseApiObject):
766 _ATTRIBUTES = { 767 'tableCount' : ROAttr(), 768 'tables' : ROAttr(ApiHiveTable), 769 'impalaUDFCount' : ROAttr(), 770 'impalaUDFs' : ROAttr(ApiImpalaUDF), 771 'errorCount' : ROAttr(), 772 'errors' : ROAttr(), 773 'dataReplicationResult' : ROAttr(ApiHdfsReplicationResult), 774 'dryRun' : ROAttr(), 775 'runAsUser' : ROAttr(), 776 'phase' : ROAttr(), 777 }
778
779 -class ApiReplicationCommand(ApiCommand):
780 @classmethod
781 - def _get_attributes(cls):
782 if not cls.__dict__.has_key('_ATTRIBUTES'): 783 attrs = { 784 'hdfsResult' : ROAttr(ApiHdfsReplicationResult), 785 'hiveResult' : ROAttr(ApiHiveReplicationResult), 786 } 787 attrs.update(ApiCommand._get_attributes()) 788 cls._ATTRIBUTES = attrs 789 return cls._ATTRIBUTES
790
791 -class ApiReplicationSchedule(BaseApiObject):
792 _ATTRIBUTES = { 793 'startTime' : Attr(datetime.datetime), 794 'endTime' : Attr(datetime.datetime), 795 'interval' : None, 796 'intervalUnit' : None, 797 'paused' : None, 798 'hdfsArguments' : Attr(ApiHdfsReplicationArguments), 799 'hiveArguments' : Attr(ApiHiveReplicationArguments), 800 'alertOnStart' : None, 801 'alertOnSuccess' : None, 802 'alertOnFail' : None, 803 'alertOnAbort' : None, 804 'id' : ROAttr(), 805 'nextRun' : ROAttr(datetime.datetime), 806 'history' : ROAttr(ApiReplicationCommand), 807 'active' : None 808 }
809
810 -class ApiHBaseSnapshotPolicyArguments(BaseApiObject):
811 _ATTRIBUTES = { 812 'tableRegExps' : None, 813 'storage' : None, 814 }
815
816 -class ApiHdfsSnapshotPolicyArguments(BaseApiObject):
817 _ATTRIBUTES = { 818 'pathPatterns' : None, 819 }
820
821 -class ApiHBaseSnapshot(BaseApiObject):
822 _ATTRIBUTES = { 823 'snapshotName' : None, 824 'tableName' : None, 825 'creationTime' : ROAttr(datetime.datetime), 826 'storage' : None, 827 }
828
829 -class ApiHBaseSnapshotError(BaseApiObject):
830 _ATTRIBUTES = { 831 'tableName' : ROAttr(), 832 'snapshotName' : ROAttr(), 833 'error' : ROAttr(), 834 'storage' : ROAttr(), 835 }
836
837 -class ApiHdfsSnapshot(BaseApiObject):
838 _ATTRIBUTES = { 839 'path' : None, 840 'snapshotName' : None, 841 'snapshotPath' : None, 842 'creationTime' : ROAttr(datetime.datetime), 843 }
844
845 -class ApiHdfsSnapshotError(BaseApiObject):
846 _ATTRIBUTES = { 847 'path' : ROAttr(), 848 'snapshotName' : ROAttr(), 849 'snapshotPath' : ROAttr(), 850 'error' : ROAttr(), 851 }
852
853 -class ApiHBaseSnapshotResult(BaseApiObject):
854 _ATTRIBUTES = { 855 'processedTableCount' : ROAttr(), 856 'processedTables' : ROAttr(), 857 'unprocessedTableCount' : ROAttr(), 858 'unprocessedTables' : ROAttr(), 859 'createdSnapshotCount' : ROAttr(), 860 'createdSnapshots' : ROAttr(ApiHBaseSnapshot), 861 'deletedSnapshotCount' : ROAttr(), 862 'deletedSnapshots' : ROAttr(ApiHBaseSnapshot), 863 'creationErrorCount' : ROAttr(), 864 'creationErrors' : ROAttr(ApiHBaseSnapshotError), 865 'deletionErrorCount' : ROAttr(), 866 'deletionErrors' : ROAttr(ApiHBaseSnapshotError), 867 }
868
869 -class ApiHdfsSnapshotResult(BaseApiObject):
870 _ATTRIBUTES = { 871 'processedPathCount' : ROAttr(), 872 'processedPaths' : ROAttr(), 873 'unprocessedPathCount' : ROAttr(), 874 'unprocessedPaths' : ROAttr(), 875 'createdSnapshotCount' : ROAttr(), 876 'createdSnapshots' : ROAttr(ApiHdfsSnapshot), 877 'deletedSnapshotCount' : ROAttr(), 878 'deletedSnapshots' : ROAttr(ApiHdfsSnapshot), 879 'creationErrorCount' : ROAttr(), 880 'creationErrors' : ROAttr(ApiHdfsSnapshotError), 881 'deletionErrorCount' : ROAttr(), 882 'deletionErrors' : ROAttr(ApiHdfsSnapshotError), 883 }
884
885 -class ApiSnapshotCommand(BaseApiObject):
886 @classmethod
887 - def _get_attributes(cls):
888 if not cls.__dict__.has_key('_ATTRIBUTES'): 889 attrs = { 890 'hdfsResult' : ROAttr(ApiHdfsSnapshotResult), 891 'hbaseResult' : ROAttr(ApiHBaseSnapshotResult), 892 } 893 attrs.update(ApiCommand._get_attributes()) 894 cls._ATTRIBUTES = attrs 895 return cls._ATTRIBUTES
896
897 -class ApiSnapshotPolicy(BaseApiObject):
898 """ 899 @type name: str 900 @ivar name: Name of the snapshot policy. 901 @type description: str 902 @ivar description: Description of the snapshot policy. 903 @type hourly_snapshots: int 904 @ivar hourly_snapshots: Number of hourly snapshots to be retained (default: 0). 905 @type daily_snapshots: int 906 @ivar daily_snapshots: Number of daily snapshots to be retained (default: 0). 907 @type weekly_snapshots: int 908 @ivar weekly_snapshots: Number of weekly snapshots to be retained (default: 0). 909 @type monthly_snapshots: int 910 @ivar monthly_snapshots: Number of monthly snapshots to be retained (default: 0). 911 @type yearly_snapshots: int 912 @ivar yearly_snapshots: Number of yearly snapshots to be retained (default: 0). 913 @type hours_for_hourly_snapshots: list of int 914 @ivar hours_for_hourly_snapshots: Hours of the day that hourly snapshots should be created. 915 Valid values are 0 to 23. If this list is empty, then hourly snapshots are 916 created for every hour. 917 @type minute_of_hour: int 918 @ivar minute_of_hour: Minute in the hour that hourly, daily, weekly, monthly and yearly 919 snapshots should be created. Valid values are 0 to 59 (default: 0). 920 @type hour_of_day: int 921 @ivar hour_of_day: Hour in the day that daily, weekly, monthly and yearly snapshots should be created. 922 Valid values are 0 to 23 (default: 0). 923 @type day_of_week: int 924 @ivar day_of_week: Day of the week that weekly snapshots should be created. 925 Valid values are 1 to 7, 1 representing Sunday (default: 1). 926 @type day_of_month: int 927 @ivar day_of_month: Day of the month that monthly and yearly snapshots should be created. 928 Values from 1 to 31 are allowed. Additionally 0 to -30 can be used to 929 specify offsets from the last day of the month (default: 1). 930 @type month_of_year: int 931 @ivar month_of_year: Month of the year that yearly snapshots should be created. 932 Valid values are 1 to 12, 1 representing January (default: 1). 933 @ivar alert_on_start: whether to generate alerts on start of snapshot creation/deletion activity. 934 @ivar alert_on_success: whether to generate alerts on successful completion of snapshot creation/deletion activity. 935 @ivar alert_on_fail: whether to generate alerts on failure of snapshot creation/deletion activity. 936 @ivar alert_on_abort: whether to generate alerts on abort of snapshot creation/deletion activity. 937 @ivar paused: whether to run the policy on schedule 938 @type hbaseArguments: ApiHBaseSnapshotPolicyArguments 939 @ivar hbaseArguments: HBase specific arguments for the replication job. 940 @type hdfsArguments: ApiHdfsSnapshotPolicyArguments 941 @ivar hdfsArguments: HDFS specific arguments for the replication job. 942 """ 943 _ATTRIBUTES = { 944 'name' : None, 945 'description' : None, 946 'hourlySnapshots' : None, 947 'dailySnapshots' : None, 948 'weeklySnapshots' : None, 949 'monthlySnapshots' : None, 950 'yearlySnapshots' : None, 951 'minuteOfHour' : None, 952 'hourOfDay' : None, 953 'dayOfWeek' : None, 954 'dayOfMonth' : None, 955 'monthOfYear' : None, 956 'hoursForHourlySnapshots' : None, 957 'alertOnStart' : None, 958 'alertOnSuccess' : None, 959 'alertOnFail' : None, 960 'alertOnAbort' : None, 961 'paused' : None, 962 'hbaseArguments' : Attr(ApiHBaseSnapshotPolicyArguments), 963 'hdfsArguments' : Attr(ApiHdfsSnapshotPolicyArguments), 964 'lastCommand' : ROAttr(ApiSnapshotCommand), 965 'lastSuccessfulCommand' : ROAttr(ApiSnapshotCommand), 966 }
967
968 # 969 # Batch. 970 # 971 972 -class ApiBatchRequestElement(BaseApiObject):
973 """One element in a batch request.""" 974 _ATTRIBUTES = { 975 'method' : None, 976 'url' : None, 977 'body' : None, 978 'contentType' : None, 979 'acceptType' : None, 980 }
981
982 -class ApiBatchResponseElement(BaseApiObject):
983 """One element in a batch response.""" 984 _ATTRIBUTES = { 985 'statusCode' : ROAttr(), 986 'response' : ROAttr(), 987 }
988
989 -class ApiBatchResponseList(ApiList):
990 """A list of batch response objects.""" 991 _ATTRIBUTES = { 992 'success' : ROAttr(), 993 } 994 _MEMBER_CLASS = ApiBatchResponseElement
995
996 # 997 # Configuration helpers. 998 # 999 1000 -class ApiConfig(BaseApiObject):
1001 _ATTRIBUTES = { 1002 'name' : None, 1003 'value' : None, 1004 'required' : ROAttr(), 1005 'default' : ROAttr(), 1006 'displayName' : ROAttr(), 1007 'description' : ROAttr(), 1008 'relatedName' : ROAttr(), 1009 'validationState' : ROAttr(), 1010 'validationMessage' : ROAttr(), 1011 'validationWarningsSuppressed' : ROAttr() 1012 } 1013
1014 - def __init__(self, resource_root, name=None, value=None):
1015 BaseApiObject.init(self, resource_root, locals())
1016
1017 - def __str__(self):
1018 return "<ApiConfig>: %s = %s" % (self.name, self.value)
1019
1020 -class ApiImpalaQuery(BaseApiObject):
1021 _ATTRIBUTES = { 1022 'queryId' : ROAttr(), 1023 'queryState' : ROAttr(), 1024 'queryType' : ROAttr(), 1025 'statement' : ROAttr(), 1026 'database' : ROAttr(), 1027 'rowsProduced' : ROAttr(), 1028 'coordinator' : ROAttr(ApiHostRef), 1029 'user' : ROAttr(), 1030 'startTime' : ROAttr(datetime.datetime), 1031 'endTime' : ROAttr(datetime.datetime), 1032 'detailsAvailable' : ROAttr(), 1033 'attributes' : ROAttr(), 1034 'durationMillis' : ROAttr() 1035 } 1036
1037 - def __str__(self):
1038 return "<ApiImpalaQuery>: %s" % (self.queryId)
1039
1040 1041 -class ApiImpalaQueryResponse(BaseApiObject):
1042 1043 _ATTRIBUTES = { 1044 'queries' : ROAttr(ApiImpalaQuery), 1045 'warnings' : ROAttr() 1046 }
1047
1048 -class ApiImpalaQueryDetailsResponse(BaseApiObject):
1049 _ATTRIBUTES = { 1050 'details' : ROAttr() 1051 } 1052
1053 - def __str__(self):
1054 return "<AipImpalaQueryDetailsResponse> %s" % self.details
1055
1056 -class ApiImpalaCancelResponse(BaseApiObject):
1057 _ATTRIBUTES = { 1058 'warning' : ROAttr() 1059 } 1060
1061 - def __str__(self):
1062 return "<ApiImpalaCancelResponse> %s" % self.warning
1063
1064 -class ApiImpalaQueryAttribute(BaseApiObject):
1065 1066 _ATTRIBUTES = { 1067 'name' : ROAttr(), 1068 'type' : ROAttr(), 1069 'displayName' : ROAttr(), 1070 'supportsHistograms' : ROAttr(), 1071 'description' : ROAttr() 1072 } 1073
1074 - def __str__(self):
1075 return "<ApiImpalaQueryAttribute> %s" % name
1076
1077 -class ApiMr2AppInformation(BaseApiObject):
1078 _ATTRIBUTES = { 1079 'jobState' : ROAttr() 1080 } 1081
1082 - def __str__(self):
1083 return "<ApiMr2AppInformation>: %s" % (self.jobState)
1084
1085 -class ApiYarnApplication(BaseApiObject):
1086 _ATTRIBUTES = { 1087 'applicationId' : ROAttr(), 1088 'name' : ROAttr(), 1089 'user' : ROAttr(), 1090 'startTime' : ROAttr(datetime.datetime), 1091 'endTime' : ROAttr(datetime.datetime), 1092 'pool' : ROAttr(), 1093 'state' : ROAttr(), 1094 'progress' : ROAttr(), 1095 'mr2AppInformation' : ROAttr(ApiMr2AppInformation), 1096 'attributes' : ROAttr(), 1097 'allocatedMB' : ROAttr(), 1098 'allocatedVCores' : ROAttr(), 1099 'runningContainers' : ROAttr(), 1100 'applicationTags' : ROAttr(), 1101 'allocatedMemorySeconds' : ROAttr(), 1102 'allocatedVcoreSeconds' : ROAttr(), 1103 'containerUsedMemorySeconds' : ROAttr(), 1104 'containerUsedCpuSeconds' : ROAttr(), 1105 'containerUsedVcoreSeconds' : ROAttr(), 1106 'containerAllocatedMemorySeconds' : ROAttr(), 1107 'containerAllocatedVcoreSeconds' : ROAttr(), 1108 } 1109
1110 - def __str__(self):
1111 return "<ApiYarnApplication>: %s" % (self.applicationId)
1112
1113 -class ApiYarnApplicationResponse(BaseApiObject):
1114 1115 _ATTRIBUTES = { 1116 'applications' : ROAttr(ApiYarnApplication), 1117 'warnings' : ROAttr() 1118 }
1119
1120 -class ApiYarnKillResponse(BaseApiObject):
1121 _ATTRIBUTES = { 1122 'warning' : ROAttr() 1123 } 1124
1125 - def __str__(self):
1126 return "<ApiYarnKillResponse> %s" % self.warning
1127
1128 -class ApiYarnApplicationAttribute(BaseApiObject):
1129 1130 _ATTRIBUTES = { 1131 'name' : ROAttr(), 1132 'type' : ROAttr(), 1133 'displayName' : ROAttr(), 1134 'supportsHistograms' : ROAttr(), 1135 'description' : ROAttr() 1136 } 1137
1138 - def __str__(self):
1139 return "<ApiYarnApplicationAttribute> %s" % name
1140
1141 -class ApiTimeSeriesRequest(BaseApiObject):
1142 _ATTRIBUTES = { 1143 'query' : None, 1144 'from' : None, 1145 'to' : None, 1146 'contentType' : None, 1147 'desiredRollup' : None, 1148 'mustUseDesiredRollup' : None 1149 } 1150
1151 - def __str__(self):
1152 return "<ApiTimeSeriesRequest>: %s" % (self.query)
1153
1154 -class ApiProductVersion(BaseApiObject):
1155 _ATTRIBUTES = { 1156 'version' : None, 1157 'product' : None, 1158 }
1159
1160 -class ApiClusterTemplateConfig(BaseApiObject):
1161 _ATTRIBUTES = { 1162 'name' : None, 1163 'value' : None, 1164 'ref' : None, 1165 'variable' : None, 1166 'autoConfig' : None, 1167 }
1168
1169 -class ApiClusterTemplateRoleConfigGroup(BaseApiObject):
1170 _ATTRIBUTES = { 1171 'refName' : None, 1172 'roleType' : None, 1173 'base' : None, 1174 'displayName' : None, 1175 'configs' : Attr(ApiClusterTemplateConfig), 1176 }
1177
1178 -class ApiClusterTemplateRole(BaseApiObject):
1179 _ATTRIBUTES = { 1180 'refName' : None, 1181 'roleType' : None, 1182 }
1183
1184 -class ApiClusterTemplateHostTemplate(BaseApiObject):
1185 _ATTRIBUTES = { 1186 'refName' : None, 1187 'cardinality' : None, 1188 'roleConfigGroupsRefNames' : None, 1189 }
1190
1191 -class ApiClusterTemplateHostInfo(BaseApiObject):
1192 _ATTRIBUTES = { 1193 'hostName' : None, 1194 'hostNameRange' : None, 1195 'rackId' : None, 1196 'hostTemplateRefName' : None, 1197 'roleRefNames' : None, 1198 }
1199
1200 -class ApiClusterTemplateVariable(BaseApiObject):
1201 _ATTRIBUTES = { 1202 'name' : None, 1203 'value' : None, 1204 }
1205
1206 -class ApiClusterTemplateRoleConfigGroupInfo(BaseApiObject):
1207 _ATTRIBUTES = { 1208 'rcgRefName' : None, 1209 'name' : None, 1210 }
1211
1212 -class ApiClusterTemplateInstantiator(BaseApiObject):
1213 _ATTRIBUTES = { 1214 'clusterName' : None, 1215 'hosts' : Attr(ApiClusterTemplateHostInfo), 1216 'variables' : Attr(ApiClusterTemplateVariable), 1217 'roleConfigGroups' : Attr(ApiClusterTemplateRoleConfigGroupInfo), 1218 }
1219
1220 -class ApiClusterTemplateService(BaseApiObject):
1221 _ATTRIBUTES = { 1222 'refName' : None, 1223 'serviceType' : None, 1224 'serviceConfigs' : Attr(ApiClusterTemplateConfig), 1225 'roleConfigGroups' : Attr(ApiClusterTemplateRoleConfigGroup), 1226 'displayName' : None, 1227 'roles' : Attr(ApiClusterTemplateRole), 1228 }
1229
1230 -class ApiClusterTemplate(BaseApiObject):
1231 _ATTRIBUTES = { 1232 'cdhVersion' : None, 1233 'displayName' : None, 1234 'cmVersion' : None, 1235 "repositories" : None, 1236 'products' : Attr(ApiProductVersion), 1237 'services' : Attr(ApiClusterTemplateService), 1238 'hostTemplates' : Attr(ApiClusterTemplateHostTemplate), 1239 'instantiator' : Attr(ApiClusterTemplateInstantiator), 1240 }
1241
1242 -def config_to_api_list(dic):
1243 """ 1244 Converts a python dictionary into a list containing the proper 1245 ApiConfig encoding for configuration data. 1246 1247 @param dic: Key-value pairs to convert. 1248 @return: JSON dictionary of an ApiConfig list (*not* an ApiList). 1249 """ 1250 config = [ ] 1251 for k, v in dic.iteritems(): 1252 config.append({ 'name' : k, 'value': v }) 1253 return { ApiList.LIST_KEY : config }
1254
1255 -def config_to_json(dic):
1256 """ 1257 Converts a python dictionary into a JSON payload. 1258 1259 The payload matches the expected "apiConfig list" type used to update 1260 configuration parameters using the API. 1261 1262 @param dic: Key-value pairs to convert. 1263 @return: String with the JSON-encoded data. 1264 """ 1265 return json.dumps(config_to_api_list(dic))
1266
1267 -def json_to_config(dic, full = False):
1268 """ 1269 Converts a JSON-decoded config dictionary to a python dictionary. 1270 1271 When materializing the full view, the values in the dictionary will be 1272 instances of ApiConfig, instead of strings. 1273 1274 @param dic: JSON-decoded config dictionary. 1275 @param full: Whether to materialize the full view of the config data. 1276 @return: Python dictionary with config data. 1277 """ 1278 config = { } 1279 for entry in dic['items']: 1280 k = entry['name'] 1281 if full: 1282 config[k] = ApiConfig.from_json_dict(entry, None) 1283 else: 1284 config[k] = entry.get('value') 1285 return config
1286