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